深入浅出设计模式 - 享元模式

news2024/11/18 16:28:21

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

在这里插入图片描述

文章目录

  • 1、什么是享元模式
  • 2、享元模式的优缺点
  • 3、享元模式的应用场景
  • 4、享元模式的结构
  • 5、享元模式的代码案例

1、什么是享元模式

享元模式是一种结构型设计模式,它通过共享对象来减少内存使用和提高性能。在享元模式中,如果多个对象需要共享相同的状态或数据,那么可以将这些状态或数据抽象出来,作为一个享元对象,由多个对象共享使用。这样可以减少对象的数量,节省内存空间,并且提高系统的性能。

享元模式中的关键是将对象的状态分为内部状态和外部状态。内部状态是可以被多个对象共享的状态,它通常是不变的,而外部状态是不可以被共享的状态,它会随着对象的不同而不同。

在实现享元模式时,通常会使用工厂类来创建享元对象,并且将已经创建的对象保存在一个池中,以便下次使用时直接从池中获取,避免重复创建对象。

享元模式可以用于需要大量相似对象的场景,例如图形编辑器中的图形对象,游戏中的角色对象等。

2、享元模式的优缺点

享元模式的优点:

  1. 减少内存消耗:通过共享对象,可以减少系统中对象的数量,从而减少内存消耗。

  2. 提高性能:由于共享对象可以避免重复创建对象,因此可以提高系统的性能。

  3. 可以实现对象的复用:通过共享对象,可以实现对象的复用,避免重复创建对象。

  4. 可以实现对象的可共享性:通过将对象的状态分为内部状态和外部状态,可以实现对象的可共享性。

享元模式的缺点:

  1. 实现较为复杂:由于享元模式需要将对象的状态分为内部状态和外部状态,并且需要使用工厂类来管理共享对象,因此实现较为复杂。

  2. 可能会影响系统的维护性:由于享元模式将对象的状态分为内部状态和外部状态,因此可能会影响系统的维护性,增加系统的复杂度。

  3. 可能会降低代码的可读性:由于享元模式需要使用工厂类来管理共享对象,因此可能会降低代码的可读性。

3、享元模式的应用场景

享元模式的应用场景:

  1. 系统中存在大量相似对象,需要缓存这些对象以提高系统性能。

  2. 对象的创建和销毁需要消耗大量的资源,需要复用对象以减少资源消耗。

  3. 对象的状态可以分为内部状态和外部状态,其中内部状态可以共享,外部状态可以变化。

  4. 系统需要提供大量的小粒度对象,需要避免创建过多的对象,以减少内存消耗。

  5. 系统需要支持大量的细粒度对象,需要将对象的状态分为内部状态和外部状态,以实现对象的复用和共享。

4、享元模式的结构

享元模式的结构包括以下几个角色:

  1. 抽象享元角色(Flyweight):定义享元对象的接口,同时可以接收外部状态作为参数。

  2. 具体享元角色(ConcreteFlyweight):实现抽象享元角色的接口,同时维护内部状态。

  3. 享元工厂角色(FlyweightFactory):负责创建和管理享元对象,维护享元池。

  4. 客户端角色(Client):使用享元对象的客户端,通过享元工厂角色获取享元对象,并传递外部状态。

5、享元模式的代码案例

我们举一个游戏的例子来说明享元模式:

package com.pany.camp.design.principle.flyweigh;

/**
 *
 * @description:  抽象享元类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:19
 */
public interface Monster {
    void attack();
}
package com.pany.camp.design.principle.flyweigh;

import java.util.HashMap;
import java.util.Map;

/**
 * @description: 常量类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:21
 */
public class Constants {
    private static Map<String, Integer> attackMap = new HashMap<>();
    private static Map<String, Integer> defenseMap = new HashMap<>();

    static {
        attackMap.put("dragon", 100);
        attackMap.put("goblin", 50);
        attackMap.put("troll", 80);
        defenseMap.put("dragon", 80);
        defenseMap.put("goblin", 20);
        defenseMap.put("troll", 50);
    }

    public static int getAttack(String type) {
        return attackMap.get(type);
    }

    public static int getDefense(String type) {
        return defenseMap.get(type);
    }
}
package com.pany.camp.design.principle.flyweigh;

/**
 *
 * @description:  具体享元类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:20
 */
public class ConcreteMonster implements Monster {

    private String type; // 内部状态

    public ConcreteMonster(String type) {
        this.type = type;
    }

    @Override
    public void attack() {
        System.out.println("攻击力:" + Constants.getAttack(type) + ",防御力:" + Constants.getDefense(type));
    }
}

package com.pany.camp.design.principle.flyweigh;

import java.util.HashMap;
import java.util.Map;

/**
 * @description: 享元工厂类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:22
 */
public class MonsterFactory {
    
    private static Map<String, Monster> monsterMap = new HashMap<>();

    public static Monster getMonster(String type) {
        Monster monster = monsterMap.get(type);
        if (monster == null) {
            monster = new ConcreteMonster(type);
            monsterMap.put(type, monster);
        }
        return monster;
    }
}
package com.pany.camp.design.principle.flyweigh;

/**
 * @description: 客户端类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:22
 */
public class Client {

    public static void main(String[] args) {
        Monster dragon = MonsterFactory.getMonster("dragon");
        dragon.attack();
        Monster goblin = MonsterFactory.getMonster("goblin");
        goblin.attack();
        Monster troll = MonsterFactory.getMonster("troll");
        troll.attack();
        Monster dragon2 = MonsterFactory.getMonster("dragon");
        dragon2.attack();
    }
}

抽象享元类为 Monster ,具体享元类为 ConcreteMonster ,享元工厂类为 MonsterFactory ,常量类为 Constants ,客户端为 Client 。当需要创建怪物时,可以通过 MonsterFactory 来获取已经创建好的怪物对象,如果对象不存在则创建新的对象并放入享元池中。这样可以避免重复创建相同的对象,提高性能。

输出如下:

攻击力:100,防御力:80
攻击力:50,防御力:20
攻击力:80,防御力:50
攻击力:100,防御力:80

在这里插入图片描述

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

初始Git

文章目录 前言技术目标协作目标 一、提出问题二、如何解决版本控制器注意事项 三、Git安装Linux-centosLinux-ubuntu 四、Git基本操作创建Git本地仓库配置Git 总结 前言 技术目标 掌握Git企业级应用,深刻理解Git操作过程与操作原理,理解工作区,暂存区,版本库的含义.掌握Git版…

LC-1595. 连通两组点的最小成本(状态压缩DP(记忆化搜索==>动态规划))

1595. 连通两组点的最小成本 难度困难86 给你两组点&#xff0c;其中第一组中有 size1 个点&#xff0c;第二组中有 size2 个点&#xff0c;且 size1 > size2 。 任意两点间的连接成本 cost 由大小为 size1 x size2 矩阵给出&#xff0c;其中 cost[i][j] 是第一组中的点 …

FineReport学习3

冻结行列&#xff08;冻结表头&#xff09; 创建多数据源之间的关联 给单元格添加过滤条件&#xff0c;让 ds2 的「客户ID」等于 ds1 的「客户ID」&#xff0c;这样两数据集就关联起来 复杂多源报表

.NETCore项目在Windows下构建Docker镜像并本地导出分发到CentOS系统下

在Windows下使用Docker&#xff0c;我们选择Docker Desktop这个软件&#xff0c;非常方便。 Docker Desktop介绍及安装 Docker Desktop是适用于Mac、Linux或Windows环境的一键安装应用程序&#xff0c;使您能够构建和共享容器化应用程序和微服务。 它提供了一个简单的GUI&…

[数据库系统] 五、数据增删改

第一关&#xff1a;数据插入 用insert给数据库添加数据 相关知识 有关系student(sno,sname,ssex,sage,sdept)&#xff0c;属性对应含义&#xff1a;学号&#xff0c;姓名&#xff0c;性别&#xff0c;所在系。现有的部分元组如下所示 insert 向数据库表插入数据的基本格式有…

生成 ocr key 字符集 alphabet 6698个字符

生成 ocr key 字符集 alphabet import pickle as pkl#----------- 生成 ocr key 字符集 alphabet alphabet_set set() # 数据集label infofiles_label [/home/jlb/下载/rec_data_lesson_demo/train.txt, /home/jlb/下载/rec_data_lesson_demo/val.txt]# ppocr中文key infofil…

SpringBoot—热部署(Community)

配置热部署 &#x1f50e;引入依赖&#x1f50e;设置 Settings 文章介绍的是社区版 Idea 配置热部署的步骤 &#x1f50e;引入依赖 复制如下代码至 pom.xml 文件中即可 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-b…

无人机遥感在农林信息提取中的实现方法与GIS融合制图教程

详情点击链接&#xff1a;无人机遥感在农林信息提取中的实现方法与GIS融合制图 遥感技术作为一种空间大数据手段&#xff0c;能够从多时、多维、多地等角度&#xff0c;获取大量的农情数据。数据具有面状、实时、非接触、无伤检测等显著优势&#xff0c;是智慧农业必须采用的重…

【夏季旅行团建】趣玩千岛湖-环湖骑行闯关-卡丁车上演速度与激情-刺激高空体验,杭州周边江浙沪团建好去处

千岛湖的秀丽景色让人惊艳&#xff0c;也是江浙沪地区热门的团建目的地之一&#xff1b; 千岛湖隶属于淳安县。从杭州自驾2个小时&#xff0c;高铁1小时&#xff0c;属于国家5A级别的人工湖&#xff0c;前身是新安江水库。拥有星罗棋布的1078个岛屿&#xff0c;是世界上岛屿最多…

AndroidStudio xml布局文件输入没有提示

AndroidStudio xml布局文件输入没有提示&#xff0c;如下图&#xff1a; 原因是老的AndroidStudio与新的sdk版本不一致 方法1&#xff1a;修改compileSdkVersion低于33即可&#xff0c;不建议 方法2&#xff1a;升级AndroidStudio版本&#xff0c;建议 如下是我的AndroidStu…

详解序列化

目录 1.什么是序列化 2.JAVA中的序列化 2.1.成员变量必须可序列化 2.2.transient关键字&#xff0c;可避免被序列化 2.3.无法更新状态 2.4.serialVersionUID 3.JDK序列化算法 4.序列化在实际中的一些应用 1.什么是序列化 序列化就是将对象转换为二进制格式的过程。对象…

MySQL的MMM高可用

MySQL的MMM高可用 一、MMM简介二、搭建MySQL的MMM高可用1、准备环境2、 搭建 MySQL 多主多从模式3、安装配置 MySQL-MMM4、故障测试5、客户端测试 一、MMM简介 MMM&#xff08;Master-Master replication manager for MvSQL&#xff0c;MySQL主主复制管理器&#xff09;是一套…

访问学者申请英语口语怎样顺利通关

想要成功申请成为访问学者&#xff0c;英语口语的流利表达是非常重要的。下面知识人网小编整理的一些帮助你顺利通关的建议&#xff1a; 1. 提前准备&#xff1a;在面试之前&#xff0c;充分准备各种常见问题的回答。练习口语表达&#xff0c;加强词汇和语法的掌握。可以通过与…

如何学习PHP语法和基本概念? - 易智编译EaseEditing

学习PHP语法和基本概念是成为一个合格的PHP开发者的第一步。以下是一些学习PHP语法和基本概念的建议&#xff1a; 官方文档&#xff1a; PHP官方提供了详细的文档&#xff0c;包括语言参考、函数参考和示例等。阅读官方文档是学习PHP语法和基本概念的最佳途径。你可以访问PHP…

企业如何数字化转型?企业数字化转型面临哪些挑战?

一文看懂&#xff1a;传统企业数字化转型会面临哪些困难与挑战&#xff1f;如何有效解决&#xff1f; 目前&#xff0c;数字技术的发展已经从互联网、大数据&#xff0c;迈入了AI人工智能时代。而企业也如逆水行舟、不进则退&#xff0c;如果不进行数字化转型&#xff0c;企业…

AI芯片的基础

前置基础 AI芯片其实就是AI算法的专用处理器&#xff0c;像CPU的话是一个通用处理器&#xff0c;CPU按照逻辑可以分为三个模块&#xff1a;控制模块&#xff0c;运算模块&#xff0c;存储模块&#xff1b;其中控制单元有指令寄存器和指令译码器&#xff0c;根据用户预先编译好…

关于Apache Dubbo反序列化漏洞(CVE-2023-23638)的预警提示与对应的Zookeeper版本

公司在升级dubbo过程中因zookeeper版本不匹配&#xff0c;导致服务注册和调用出现异常 一、漏洞详情 Apache Dubbo是一款高性能、轻量级的开源Java服务框架。 Apache官方发布安全公告&#xff0c;修复了Apache Dubbo中的一个反序列化漏洞&#xff08;CVE-2023-23638&#xff…

系统架构设计师 5:软件工程

一、软件工程 1 软件过程模型 软件要经历从需求分析、软件设计、软件开发、运行维护&#xff0c;直至被淘汰这样的全过程&#xff0c;这个全过程称为软件的生命周期。 为了使软件生命周期中的各项任务能够有序地按照规程进行&#xff0c;需要一定的工作模型对各项任务给予规…

不会设计也能轻松制作商品宣传海报图片,只要跟着这个教程走

促销活动是商家吸引顾客的重要方式之一&#xff0c;而宣传海报则是促销活动中的主要宣传工具之一。好的宣传海报可以让顾客对活动产生兴趣&#xff0c;提高产品的曝光率。然而&#xff0c;对于小型商家来说&#xff0c;往往没有专业的设计人员&#xff0c;如何制作出符合自己需…

项目开发中的安全问题怎么处理?

目录 1.客户的数据不可信 2. 客户端提交的参数需要校验 3.请求头里的内容出现错误 1.客户的数据不可信 PostMapping("/order") public void wrong(RequestBody Order order) {this.createOrder(order); } 对应的实体类如下&#xff1a; Data public class Order …