Malize's blog Malize's blog
首页
  • 设计模式

    • 设计模式总览
    • 工作中用到的设计模式
  • 并发编程

    • 死锁
  • 技术文档

    • Docker 核心命令大全
    • Markdown 使用教程
    • npm 常用命令
    • yaml 语言教程
    • Nodejs 递归读文件
  • 构造问答系统

    • 项目背景
    • 构建答疑机器人
    • 扩展知识范围
    • 优化提示词
    • 自动化评测
    • 优化 RAG 应用
  • 构建 Agent 系统

    • Agent 基础与工具调用
    • 规划与执行
    • 多 Agent 团队协作
    • Memory 积累经验
    • Skill 可复用流程
    • Qwen Code 实践
  • 交付上线

    • 走向生产环境
    • 模型蒸馏
    • 部署模型
    • 生产实践
    • 安全合规
  • 工具手册

    • OpenClaw 命令速查
  • 规范 & 实践

    • 代码规范
    • sharding-jdbc
    • CIM 半导体行业
    • HTML 常用 meta
    • CSS 技巧收藏
  • 微服务

    • feign原理
  • Git

    • Git 笔记总览
    • Git 使用手册
    • Git 修改分支名
    • 团队 Git 分支规范
  • GitHub & 博客

    • GitHub 高级搜索技巧
    • GitHub Actions 自动部署
    • 博客搭建 - 百度收录
  • 优质网站
  • 前端库推荐
  • 成长学习

    • 学习方法
    • 敏捷开发实战
    • 提示词工程
  • 生活

    • 实用技巧
    • 心情杂货
    • 梦境与灵感
  • 技术问题

    • 面试问题备忘
  • 索引

    • 分类
    • 标签
    • 按年归档
GitHub (opens new window)

Malize

持续学习,持续成长
首页
  • 设计模式

    • 设计模式总览
    • 工作中用到的设计模式
  • 并发编程

    • 死锁
  • 技术文档

    • Docker 核心命令大全
    • Markdown 使用教程
    • npm 常用命令
    • yaml 语言教程
    • Nodejs 递归读文件
  • 构造问答系统

    • 项目背景
    • 构建答疑机器人
    • 扩展知识范围
    • 优化提示词
    • 自动化评测
    • 优化 RAG 应用
  • 构建 Agent 系统

    • Agent 基础与工具调用
    • 规划与执行
    • 多 Agent 团队协作
    • Memory 积累经验
    • Skill 可复用流程
    • Qwen Code 实践
  • 交付上线

    • 走向生产环境
    • 模型蒸馏
    • 部署模型
    • 生产实践
    • 安全合规
  • 工具手册

    • OpenClaw 命令速查
  • 规范 & 实践

    • 代码规范
    • sharding-jdbc
    • CIM 半导体行业
    • HTML 常用 meta
    • CSS 技巧收藏
  • 微服务

    • feign原理
  • Git

    • Git 笔记总览
    • Git 使用手册
    • Git 修改分支名
    • 团队 Git 分支规范
  • GitHub & 博客

    • GitHub 高级搜索技巧
    • GitHub Actions 自动部署
    • 博客搭建 - 百度收录
  • 优质网站
  • 前端库推荐
  • 成长学习

    • 学习方法
    • 敏捷开发实战
    • 提示词工程
  • 生活

    • 实用技巧
    • 心情杂货
    • 梦境与灵感
  • 技术问题

    • 面试问题备忘
  • 索引

    • 分类
    • 标签
    • 按年归档
GitHub (opens new window)
  • 工作中用到的设计模式
  • 享元模式
    • 单例模式
    • 原型模式
    • 备忘录模式
    • 外观模式
    • 工厂方法模式
    • 模板方法模式
    • 策略模式
    • 装饰模式
    • 访问者模式
    • 责任链模式
    • 适配器模式
    • 中介者模式
    • 设计模式
    malize
    2020-11-18
    目录

    享元模式原创

    # 享元模式

    # 一、享元模式

    1. 原理:享元模式是一种结构型设计模式, 它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的内存容量中载入更多对象。

    2. 优缺点

      1. 1 优点
      • 减少内存使用: 通过共享相似对象的公共部分,可以减少内存使用量,特别是当系统中存在大量相似对象时,这种节省可以显著提高性能和减少资源消耗。
      • 提高性能: 由于减少了对象的数量,因此在创建和销毁对象时的开销也相应减少,可以提高系统的性能。
      • 提高可维护性: 享元模式将对象的状态分为内部状态和外部状态,内部状态是可以共享的,外部状态是不可共享的。这种区分有助于更好地管理对象状态,使得系统更易于维护。
      • 支持大规模对象: 享元模式适用于需要大量相似对象的场景,例如图形编辑器中的图元对象,文档编辑器中的字符对象等。
      1. 2 缺点
      • 复杂性增加: 享元模式引入了共享对象池和状态管理机制,这增加了系统的复杂性,使得代码变得更加难以理解和维护。
      • 可能引入线程安全问题: 如果享元对象被多个线程同时访问和修改,可能会引入线程安全问题,需要额外的同步机制来保证对象的状态不被破坏。
      • 可能引入性能问题: 尽管享元模式可以减少内存使用和对象数量,但在某些情况下,共享对象的创建和管理可能会引入额外的性能开销,特别是在对象的状态转换复杂或者需要频繁修改状态时。
      • 对外部状态的管理: 在享元模式中,需要额外的机制来管理外部状态,例如在享元对象外部维护状态信息的数据结构,这增加了系统的复杂性和开发成本。
    3. 适用场景

      • 大量相似对象: 当系统中存在大量相似对象,并且这些对象的区别主要在于它们的内部状态时,可以使用享元模式来共享这些相似对象的内部状态,减少内存消耗。
      • 频繁创建和销毁对象: 如果系统中频繁创建和销毁对象,而且创建对象的开销比较大,可以使用享元模式来缓存已经创建的对象,避免重复创建,提高系统性能。
      • 对象数量巨大: 在需要管理大量对象的系统中,例如图形编辑器、文档编辑器等,通过享元模式可以有效地减少对象的数量,减少系统的内存消耗和资源占用。
      • 对象的状态可以分为内部状态和外部状态: 如果对象的状态可以分为内部状态和外部状态,并且内部状态可以共享,外部状态可以通过参数传递的方式进行管理,那么可以使用享元模式来提高系统的效率。
      • 需要缓存对象以提高性能: 在需要缓存对象以提高系统性能的场景中,可以使用享元模式来缓存对象,避免重复创建和销毁对象,提高系统的响应速度。

    # 二、享元模式基本代码

    1. 享元接口

      interface Shape {
          void draw();
      }
      
      1
      2
      3
    2. 具体享元类

      class Circle implements Shape {
          private String color;
      
          public Circle(String color) {
              this.color = color;
          }
      
          @Override
          public void draw() {
              System.out.println("Drawing Circle with color: " + color);
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
    3. 享元工厂类

      class ShapeFactory {
          private static final HashMap<String, Shape> circleMap = new HashMap<>();
      
          // 获取圆形对象
          public static Shape getCircle(String color) {
              Circle circle = (Circle) circleMap.get(color);
      
              // 如果不存在该颜色的圆形,则创建一个新的圆形对象并放入享元池中
              if (circle == null) {
                  circle = new Circle(color);
                  circleMap.put(color, circle);
                  System.out.println("Creating new Circle with color: " + color);
              }
              
              return circle;
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
    4. 客户端

      public class Main {
          private static final String[] colors = { "Red", "Green", "Blue", "Yellow", "Black" };
      
          public static void main(String[] args) {
              // 模拟绘制不同颜色的圆形
              for (int i = 0; i < 10; ++i) {
                  String color = colors[(int) (Math.random() * colors.length)];
                  Shape circle = ShapeFactory.getCircle(color);
                  circle.draw();
              }
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12

    # 三、实现方式

    1. 将需要改写为享元的类成员变量拆分为两个部分:
      • 内在状态: 包含不变的、 可在许多对象中重复使用的数据的成员变量。
      • 外在状态: 包含每个对象各自不同的情景数据的成员变量
    2. 保留类中表示内在状态的成员变量, 并将其属性设置为不可修改。 这些变量仅可在构造函数中获得初始数值。
    3. 找到所有使用外在状态成员变量的方法, 为在方法中所用的每个成员变量新建一个参数, 并使用该参数代替成员变量。
    4. 你可以有选择地创建工厂类来管理享元缓存池, 它负责在新建享元时检查已有的享元。 如果选择使用工厂, 客户端就只能通过工厂来请求享元, 它们需要将享元的内在状态作为参数传递给工厂。
    5. 客户端必须存储和计算外在状态 (情景) 的数值, 因为只有这样才能调用享元对象的方法。 为了使用方便, 外在状态和引用享元的成员变量可以移动到单独的情景类中。
    编辑 (opens new window)
    #重学Java设计模式
    工作中用到的设计模式
    单例模式

    ← 工作中用到的设计模式 单例模式→

    最近更新
    01
    feign原理
    07-15
    02
    团队Git分支管理、迭代发布、分批投产标准化规范
    07-15
    03
    面试问题备忘
    07-07
    更多文章>
    Theme by Vdoing | Copyright © 2023-2026 Malize | GitHub | 桂ICP备2024034950号 | 桂公网安备45142202000030
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式