Gof23设计模式之享元模式

1.定义

运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销,从而提高系统资源的利用率。

2.结构

享元(Flyweight )模式中存在以下两种状态:

  1. 内部状态,即不会随着环境的改变而改变的可共享部分。
  2. 外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。

享元模式的主要有以下角色:

  • 抽象享元角色(Flyweight):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)。
  • 具体享元(Concrete Flyweight)角色 :它实现了抽象享元类,称为享元对象;在具体享元类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。
  • 非享元(Unsharable Flyweight)角色 :并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。
  • 享元工厂(Flyweight Factory)角色 :负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

3.案例实现

下面的图片是众所周知的俄罗斯方块中的一个个方块,如果在俄罗斯方块这个游戏中,每个不同的方块都是一个实例对象,这些对象就要占用很多的内存空间,下面利用享元模式进行实现。
在这里插入图片描述
俄罗斯方块有不同的形状,我们可以对这些形状向上抽取出AbstractBox,用来定义共性的属性和行为。

/**
 * @author 晓风残月Lx
 * @date 2023/7/13 0:10
 *      抽象享元角色
 */
public abstract class AbstractBox {

    // 获取图形的方法
    public abstract String getShape();

    // 显示图形及颜色
    public void display(String color) {
        System.out.println("方块形状:" + getShape() + ",方块颜色:" + color);
    }
}

接下来就是定义不同的形状了,IBox类、LBox类、OBox类等。

/**
 * @author 晓风残月Lx
 * @date 2023/7/13 0:13
 *      I 图形类(具体享元角色)
 */
public class IBow extends AbstractBox {

    @Override
    public String getShape() {
        return "I";
    }
}


/**
 * @author 晓风残月Lx
 * @date 2023/7/13 0:13
 *      L图形类(具体享元角色)
 */
public class LBow extends AbstractBox {

    @Override
    public String getShape() {
        return "L";
    }
}


/**
 * @author 晓风残月Lx
 * @date 2023/7/13 0:13
 *      O图形类(具体享元角色)
 */
public class OBow extends AbstractBox {

    @Override
    public String getShape() {
        return "O";
    }

}

提供了一个工厂类(BoxFactory),用来管理享元对象(也就是AbstractBox子类对象),该工厂类对象只需要一个,所以可以使用单例模式。并给工厂类提供一个获取形状的方法。


import java.util.HashMap;

/**
 * @author 晓风残月Lx
 * @date 2023/7/13 0:16
 *      享元工厂   设计为单例
 */
public class BoxFactory {

    private HashMap<String, AbstractBox> map;

    private static BoxFactory boxFactory = new BoxFactory();

    // 初始化
    private BoxFactory() {
        map = new HashMap<String, AbstractBox>();
        map.put("I", new IBow());
        map.put("L", new LBow());
        map.put("O", new OBow());
    }

    // 获取单例对象
    public static BoxFactory getInstance() {
        return boxFactory;
    }

    // 根据名称获取图形对象
    public AbstractBox getShape(String name) {
        return map.get(name);
    }

}

测试类

/**
 * @author 晓风残月Lx
 * @date 2023/7/13 0:20
 */
public class Client {

    public static void main(String[] args) {
        // 获取I图形对象
        AbstractBox l = BoxFactory.getInstance().getShape("L");
        l.display("蓝色");

        AbstractBox o = BoxFactory.getInstance().getShape("O");
        o.display("黄色");

        AbstractBox o1 = BoxFactory.getInstance().getShape("O");
        o1.display("红色");

        System.out.println("是否同一对象:" + (o == o1));
    }
}

在这里插入图片描述

4.优缺点和使用场景

1,优点

  • 极大减少内存中相似或相同对象数量,节约系统资源,提供系统性能
  • 享元模式中的外部状态相对独立,且不影响内部状态

2,缺点:

为了使对象可以共享,需要将享元对象的部分状态外部化,分离内部状态和外部状态,使程序逻辑复杂

3,使用场景:

  • 一个系统有大量相同或者相似的对象,造成内存的大量耗费。
  • 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
  • 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。

5.JDK源码解析

Integer类使用了享元模式。在Integer类中维护了一个IntegerCache类,在valueOf方法中可以看到 Integer 默认先创建并缓存 -128 ~ 127 之间数的 Integer对象,当调用 valueOf 时如果参数在 -128 ~ 127之间则计算下标并从缓存中返回,否则创建一个新的 Integer 对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/63955.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

webpack基础知识三:说说webpack中常见的Loader?解决了什么问题?

一、是什么 loader 用于对模块的"源代码"进行转换&#xff0c;在 import 或"加载"模块时预处理文件 webpack做的事情&#xff0c;仅仅是分析出各种模块的依赖关系&#xff0c;然后形成资源列表&#xff0c;最终打包生成到指定的文件中。如下图所示&#…

使用 RediSearch 在 Redis 中进行全文检索

原文链接&#xff1a; 使用 RediSearch 在 Redis 中进行全文检索 Redis 大家肯定都不陌生了&#xff0c;作为一种快速、高性能的键值存储数据库&#xff0c;广泛应用于缓存、队列、会话存储等方面。 然而&#xff0c;Redis 在原生状态下并不支持全文检索功能&#xff0c;这使…

linux初始命令

如果没有ip地址&#xff0c;配置&#xff1a; 查看当前时间&#xff1a; 指定格式查看时间&#xff1a; 修改时间&#xff1a; 查看时区&#xff1a; 设置时区&#xff1a; 查看当前工作目录&#xff1a; root的家目录就是根&#xff0c;普通用户家目录是home

ctfshow-web7

0x00 前言 CTF 加解密合集 CTF Web合集 0x01 题目 0x02 Write Up 通过尝试&#xff0c;发现是数字型的注入&#xff0c;并且同样是过滤了空格 判断字段 获取一下flag即可 1/**/union/**/select/**/1,flag,3/**/from/**/web7.flag#&passworda以上

MySQL日期常见的函数

-- 获取当天日期 -- 2023-06-20 select curdate();-- 获取当天年月日时分秒 select now();-- 日期运算 -- 2024-06-20 17:04:17 select date_add(now(),interval 1 year);-- 日期比较 -- 0 select datediff(now(),now());-- 日期MySQL对于日期类型数据如何查询 -- 获取指定日期…

【果树农药喷洒机器人】Part4:果树冠层图像实例分割模型优化

文章目录 一、引言二、数据集制作2.1图像采集2.2图像标注与增强 三、构建柑橘树冠实例分割模型结构3.1优化特征提取网络3.2U-Net替换FCN 一、引言 为准确获取柑橘树冠的生长信息&#xff0c;实现果树喷药机器人的精准喷施&#xff0c;对处于多种生长阶段的柑橘树冠进行图像分割…

ffmpeg源码编译成功,但是引用生成的静态库(.a)报错,报错位置在xxx_list.c,报错信息为某变量未定义

背景&#xff1a;本文是对上一个文章的补充&#xff0c;在源码编译之前&#xff0c;项目是有完整的ffmpeg编译脚本的&#xff0c;只不过新增了断点调试ffmpeg&#xff0c;所以产生的上面的文章&#xff0c;也就是说&#xff0c;我在用make编译成功后&#xff0c;再去做的源码编…

dfs之卒的遍历

题面 题目描述 在一张nm 的棋盘上&#xff08;如 6 行 7 列&#xff09;的最左上角(1,1) 的位置有一个卒。该卒只能向下或者向右走&#xff0c;且卒采取的策略是先向下&#xff0c;下边走到头就向右&#xff0c;请问从(1,1) 点走到 (n,m) 点可以怎样走&#xff0c;输出这些走法…

【软件工程】5 ATM系统测试

目录 5 ATM系统测试 5.1 单元测试 5.1.1 制定单元测试计划 5.1.2 设计单元测试用例 ​编辑 5.1.3 执行单元测试 5.1.4 单元测试报告 5.2 集成测试 5.2.1 制定集成测试计划 5.2.2 设计集成测试用例 5.2.3 执行集成测试 5.2.4 集成测试总结 5.3 系统测试 5.3.1 制定…

2023 年实验班选拔试题

比赛链接&#xff0c;邀请码&#xff1a;2023qsb A Zlz’s problem(Easy Version) 题目描述 This is the easy version of this problem. The only difference between the easy and hard versions is the constraints on n n n and m m m. So I won’t even take a glan…

Docker网络模式详解

目录 Docker网络模式 一、Host模式 二、container模式 三、none模式 四、bridge模式 五、Overlay模式 Docker网络模式 安装Docker时会自动创建3个网络&#xff0c;可以使用docker network ls命令列出这些网络。 [rootdocker ~]# docker network ls 我们在使用docker run…

摄像机终端IP地址白名单配置流程

海康摄像头配置白名单流程 1.登录海康摄像机前端 2.进入配置-系统-安全管理-IP地址过滤 3.IP地址过滤方式选择“允许” 4.点击添加按钮输入对应的IP地址或者IP网段 5.最后勾选启用IP地址过滤&#xff0c;然后保存 大华摄像头配置白名单流程 1.登录大华摄像机前端 2.进入设…

自动驾驶传感器选型

360的场景&#xff0c;避免有盲区&#xff0c;长距离 Lidar&#xff08;激光雷达&#xff09; 典型特点一圈一圈的&#xff0c;轮廓和很高的位置精度 禾赛的机械雷达 速腾的固态雷达 固态雷达是车规级的&#xff0c;车规级的意思是可以装到量产车上 Radar&#xff08;毫米…

解决Vue+Element UI使用表单rules国际化时From表单验证信息不能实时更新

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 博主在工作之余开始进行自动化测试平台的开发&#xff0c;虽然已经996一个月了但是还是在使劲挤时间做这件事情&#xff0c;目前平台使用前端框架vu…

秋招打卡011(20230807)

文章目录 前言一、今天学习了什么&#xff1f;二、算法----》单调栈1、介绍2、题目 总结 前言 提示&#xff1a;这里为每天自己的学习内容心情总结&#xff1b; Learn By Doing&#xff0c;Now or Never&#xff0c;Writing is organized thinking. 今天拿到了上周面试的结果…

Docker实战-如何去访问Docker仓库?

导语   仓库在之前的分享中我们介绍过,它主要的作用就是用来存放镜像文件,又可以分为是公共的仓库和私有仓库。有点类似于Maven的中央仓库和公司内部私服。 下面我们就来介绍一下在Docker中如何去访问各种仓库。 Docker Hub 公共镜像仓库 Docker Hub 是Docker官方提供的最…

恺英网络宣布:与华为鸿蒙系统展开合作,将开发多款手游

8月5日消息&#xff0c;恺英网络宣布旗下子公司盛和网络参加了华为开发者大会&#xff08;HDC.Together&#xff09;游戏服务论坛&#xff0c;并在华为鸿蒙生态游戏先锋合作启动仪式上进行了亮相。恺英网络表示&#xff0c;将逐步在HarmonyOS上开发多款游戏&#xff0c;利用Har…

使用C#的窗体显示与隐藏动画效果方案 - 开源研究系列文章

今天继续研究C#的WinForm的显示动画效果。 上次我们实现了无边框窗体的显示动画效果(见博文&#xff1a;基于C#的无边框窗体动画效果的完美解决方案 - 开源研究系列文章 )&#xff0c;这次介绍的是未在任务栏托盘中窗体的显示隐藏动画效果的实现代码。 1、 项目目录&#xff1b…

tomcat配置文件和web站点部署(zrlog)简介

一.tomcat/apache-tomcat-8.5.70/conf/server.xml组件类别介绍 1.类别 2.Connector参数 3.host参数 4.Context参数 二.web站点部署(以zrlog为例) 1.将zrlog的war包传到webapps下面 2.在mysql数据库中创建zrlog用户并赋予权限 3.完成安装向导&#xff0c;登录管理界面即可…

睡眠助手/白噪音/助眠夜曲微信小程序源码 附教程

简介&#xff1a; 睡眠助手/白噪音/助眠夜曲微信小程序源码 附教程 支持分享海报 支持暗黑模式 包含了音频数据 最近很火的助眠小程序&#xff0c;前端vue&#xff0c;可以打包H5&#xff0c;APP&#xff0c;小程序 后台可以设置流量主广告&#xff0c;非常不错的源码 代码完…