「全网最细 + 实战源码案例」设计模式——享元模式

简介: 享元模式(Flyweight Pattern)是一种结构型设计模式,旨在减少大量相似对象的内存消耗。通过分离对象的内部状态(可共享、不变)和外部状态(依赖环境、变化),它有效减少了内存使用。适用于存在大量相似对象且需节省内存的场景。模式优点包括节省内存和提高性能,但会增加系统复杂性。实现时需将对象成员变量拆分为内在和外在状态,并通过工厂类管理享元对象。

核心思想

  • 享元模式(Flyweight Pattern)是一种结构型设计模式,主要用于减少程序中大量对象的内存消耗。该模式通过共享相同的数据来有效减少内存的使用,适用于对象非常多且可以共享一部分状态的场景。
  • 核心:将对象的内部状态外部状态分离
    • 内部状态:存储在享元对象内部的、不会改变的状态,通常是可以共享的。
    • 外部状态:依赖于环境且变化的状态,不可共享。

编辑


结构

1. Flyweight(享元角色)

  • 声明享元对象的接口,通常是不可变的。

2. ConcretFlyweight(具体享元角色)

  • 实现 Flyweight 接口,存储共享状态。

3. UnsharedConcreteFlyweight(非共享具体享元角色)

  • 非共享的享元对象,一般不是由享元工厂创建。

4. FlyweightFactory(享元工厂)

  • 用来管理享元对象的工厂类,确保共享对象的唯一性。

编辑


适用场景

  1. 存在大量相似对象
  2. 对象状态可分为内部、外部状态
  3. 节省内存,避免重复创建对象。

优缺点

优点:

  1. 节省内存:避免重复创建相似对象。
  2. 提高性能:减少重复创建对象的开销。

缺点:

  1. 增加复杂性:享元模式、工厂类的设计。

实现步骤

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

示例

编辑

编辑

// 享元角色
public abstract class AbstractBox {

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

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

// 具体享元角色——I
public class IBox extends AbstractBox{
    @Override
    public String getShape() {
        return "I";
    }
}

// 具体享元角色——L
public class LBox extends AbstractBox{
    @Override
    public String getShape() {
        return "L";
    }
}

// 具体享元角色——O
public class OBox extends AbstractBox{
    @Override
    public String getShape() {
        return "O";
    }
}

// 享元工厂(静态内部类单例方式)
public class BoxFactory {

    // 享元对象池
    private Map<String, AbstractBox> boxes;

    // 私有化构造器
    private BoxFactory() {
        boxes = new HashMap<>();
        boxes.put("L", new LBox());
        boxes.put("I", new IBox());
        boxes.put("O", new OBox());
    }

    // 获取享元对象
    public AbstractBox getBox(String type) {
        return boxes.get(type);
    }

    // 创建静态内部类
    private static class SingletonHolder {
        private static final BoxFactory INSTANCE = new BoxFactory();
    }

    // 获取享元工厂实例
    public static BoxFactory getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {

        // 1.获取享元工厂
        BoxFactory boxFactory = BoxFactory.getInstance();

        // 2.获取享元对象
        AbstractBox box1 = boxFactory.getBox("L");
        AbstractBox box2 = boxFactory.getBox("I");
        AbstractBox box3 = boxFactory.getBox("O");
        AbstractBox box4 = boxFactory.getBox("O");

        // 3.获取非享元对象并显示
        box1.display("red");
        box2.display("blue");
        box3.display("green");
        box4.display("yellow");

        // 4.验证享元对象是否共享
        System.out.println(box3 == box4);

    }
}


在源码中的应用

编辑

编辑

编辑

编辑


与其他模式的关系

  • 你可以使用享元模式实现组合模式树的共享叶节点以节省内存。
  • 享元展示了如何生成大量的小型对象, 外观模式则展示了如何用一个对象来代表整个子系统。
  • 如果你能将对象的所有共享状态简化为一个享元对象, 那么享元就和单例模式类似了。 但这两个模式有两个根本性的不同。
    • 只会有一个单例实体, 但是享元类可以有多个实体, 各实体的内在状态也可以不同。
    • 单例对象可以是可变的。 享元对象是不可变的。

目录
相关文章
|
4天前
|
设计模式 人工智能 算法
基于多设计模式的状态扭转设计:策略模式与责任链模式的实战应用
接下来,我会结合实战案例,聊聊如何用「策略模式 + 责任链模式」构建灵活可扩展的状态引擎,让抽奖系统的状态管理从「混乱战场」变成「有序流水线」。
设计模式 存储 人工智能
46 0
|
2月前
|
设计模式 C++
【实战指南】设计模式 - 工厂模式
工厂模式是一种面向对象设计模式,通过定义“工厂”来创建具体产品实例。它包含简单工厂、工厂方法和抽象工厂三种形式,分别适用于不同复杂度的场景。简单工厂便于理解但扩展性差;工厂方法符合开闭原则,适合单一类型产品创建;抽象工厂支持多类型产品创建,但不便于新增产品种类。三者各有优缺点,适用于不同设计需求。
109 35
|
3月前
|
设计模式 存储 缓存
Netty源码—9.性能优化和设计模式
本文主要介绍了Netty的两大性能优化工具、FastThreadLocal的源码和总结、Recycler的设计理念/使用/四个核心组件/初始化/对象获取/对象回收/异线程收割对象和总结,以及Netty设计模式的单例模式和策略模式。
146 53
|
4月前
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
104 0
|
4月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
126 0
|
4月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
112 0
|
4月前
|
设计模式 运维 监控
并发设计模式实战系列(4):线程池
需要建立持续的性能剖析(Profiling)和调优机制。通过以上十二个维度的系统化扩展,构建了一个从。设置合理队列容量/拒绝策略。动态扩容/优化任务处理速度。检查线程栈定位热点代码。调整最大用户进程数限制。CPU占用率100%
315 0
|
4月前
|
设计模式 消息中间件 监控
并发设计模式实战系列(3):工作队列
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第三章,废话不多说直接开始~
87 0
|
4月前
|
设计模式 消息中间件 监控
并发设计模式实战系列(5):生产者/消费者
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第五章,废话不多说直接开始~
143 1