【设计模式】享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享尽可能多的对象来有效支持大量细粒度的对象。这个模式主要用于减少内存使用和提高性能,特别是在需要创建大量相似对象的场景中。享元模式的核心思想是将对象的状态分为内在状态(Intrinsic State)和外在状态(Extrinsic State),其中内在状态存储在对象内部,并且对于所有引用该对象的地方都是相同的;而外在状态则由客户端管理并传递给对象。

享元模式的关键要素

  1. Flyweight (享元)

    这是一个接口或抽象类,声明了具体享元类应该实现的操作。

    它定义了哪些方法可以访问内在状态,以及如何接收外在状态。

    java

    深色版本

    public interface Flyweight {

    void operation(int extrinsicState);

    }

  2. ConcreteFlyweight (具体享元)

    实现 Flyweight 接口的具体类。

    包含内在状态,并且可能会根据传入的外在状态执行不同的操作。

    java

    深色版本

    public class ConcreteFlyweight implements Flyweight {

    private final String intrinsicState;

    public ConcreteFlyweight(String intrinsicState) {

    this.intrinsicState = intrinsicState;

    }

    @Override

    public void operation(int extrinsicState) {

    System.out.println("Intrinsic State = " + this.intrinsicState);

    System.out.println("Extrinsic State = " + extrinsicState);

    }

    }

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

    如果某些对象不能被共享,或者它们包含的全部是外在状态,则可以创建非共享的具体享元类。

    这些对象不会被池化管理,而是直接由客户端创建和销毁。

    java

    深色版本

    public class UnsharedConcreteFlyweight implements Flyweight {

    @Override

    public void operation(int extrinsicState) {

    // 操作逻辑

    }

    }

  4. FlyweightFactory (享元工厂)

    负责管理和创建享元对象。

    它通常维护一个享元对象的缓存(如 HashMap),以确保相同内在状态的对象只创建一次,并能在后续请求时返回已存在的实例。

    java

    深色版本

    import java.util.HashMap;

    import java.util.Map;

public class FlyweightFactory {

private final Map<String, Flyweight> flyweights = new HashMap<>();

复制代码
public Flyweight getFlyweight(String key) {
    return flyweights.computeIfAbsent(key, k -> new ConcreteFlyweight(k));
}

}

使用享元模式的好处

节省内存:通过共享不可变的部分,减少了内存占用。

提升性能:当需要频繁创建和销毁大量相似对象时,享元模式可以通过重用现有对象来加快程序运行速度。

简化对象管理:客户端只需要关心外在状态,而不需要处理每个对象的所有细节。

示例应用场景

文本编辑器中的字符格式:在一个大型文档中,如果每个字符都单独保存其字体、颜色等属性信息,将会消耗大量的内存。使用享元模式,可以将这些格式信息作为内在状态进行共享,而将字符位置等信息作为外在状态由客户端管理。

GUI 系统中的图标:对于 GUI 应用程序,可能有多个组件使用相同的图标。通过享元模式,可以确保每个唯一的图标只加载一次,并且可以在不同地方重复使用。

游戏开发中的敌人角色:在一些游戏中,同一类型的敌人角色可能具有相同的外观和行为。使用享元模式,可以将这些共同特征作为内在状态,而将位置、健康值等变化的数据作为外在状态。

注意事项

内外状态分离:正确区分内在状态和外在状态是成功应用享元模式的关键。内在状态应该是不可变的,而外在状态则是可变的并且由客户端提供。

线程安全问题:如果享元对象将在多线程环境中使用,必须确保内在状态的线程安全性。由于内在状态是不可变的,因此这通常不是问题,但仍然需要注意任何可能影响到对象共享的行为。

总之,享元模式适用于那些需要高效地管理大量相似对象的应用程序。通过合理利用对象共享机制,它可以显著降低系统资源消耗,同时保持良好的性能表现。

相关推荐
cynicme3 小时前
力扣3318——计算子数组的 x-sum I(偷懒版)
java·算法·leetcode
青云交4 小时前
Java 大视界 -- Java 大数据在智能教育学习效果评估与教学质量改进实战
java·实时分析·生成式 ai·个性化教学·智能教育·学习效果评估·教学质量改进
崎岖Qiu4 小时前
【设计模式笔记17】:单例模式1-模式分析
java·笔记·单例模式·设计模式
Lei活在当下4 小时前
【现代 Android APP 架构】09. 聊一聊依赖注入在 Android 开发中的应用
java·架构·android jetpack
不穿格子的程序员5 小时前
从零开始刷算法-栈-括号匹配
java·开发语言·
lkbhua莱克瓦245 小时前
Java练习-正则表达式 1
java·笔记·正则表达式·github
yue0085 小时前
C#类继承
java·开发语言·c#
凯芸呢6 小时前
Java中的数组(续)
java·开发语言·数据结构·算法·青少年编程·排序算法·idea
竹竹零6 小时前
JacksonUtil--序列化与反序列化
java·开发语言·windows
钱多多_qdd6 小时前
基础篇:IoC(三):Bean实例化策略InstantiationStrategy
java·spring