14. 享元模式vs单例模式


享元模式 vs. 单例模式

1. 核心目标
模式核心目标
享元模式共享多个对象:通过复用相同内部状态的对象,减少内存占用和对象创建开销。
单例模式限制唯一实例:确保一个类仅有一个实例,并提供全局访问点,通常用于控制资源或共享服务。

2. 关键区别
维度享元模式单例模式
实例数量可以有多个实例(每个享元对应不同的内部状态)。严格仅有一个实例。
状态管理区分内部状态(共享)和外部状态(非共享),依赖外部状态传入。单例通常管理自身状态,所有客户端共享同一状态。
适用场景存在大量重复对象的场景(如游戏中的子弹、文本编辑器中的字符)。需要全局唯一访问点的场景(如配置管理、数据库连接池)。
实现方式使用工厂类管理共享对象池,按需返回享元对象。通过私有构造函数和静态方法确保唯一实例。
线程安全享元对象若仅包含不可变状态则线程安全,否则需处理外部状态的线程安全。需显式处理多线程环境下的实例化问题(如双重检查锁定)。

3. 代码对比
享元模式示例
// 享元接口
interface Flyweight {
    void operation(String extrinsicState);
}

// 具体享元(可存在多个不同内部状态的实例)
class ConcreteFlyweight implements Flyweight {
    private final String intrinsicState; // 内部状态(不可变)

    public ConcreteFlyweight(String state) {
        this.intrinsicState = state;
    }

    @Override
    public void operation(String extrinsicState) {
        System.out.println("Intrinsic: " + intrinsicState + ", Extrinsic: " + extrinsicState);
    }
}

// 享元工厂(管理多个享元实例)
class FlyweightFactory {
    private final Map<String, Flyweight> pool = new HashMap<>();

    public Flyweight getFlyweight(String key) {
        return pool.computeIfAbsent(key, ConcreteFlyweight::new);
    }
}
单例模式示例
// 单例类(仅有一个实例)
class Singleton {
    private static volatile Singleton instance; // 唯一实例

    private Singleton() {} // 私有构造函数

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    public void doSomething() {
        System.out.println("Singleton action");
    }
}

4. 结合使用场景
  • 互补场景
    享元工厂本身可以实现为单例,确保全局统一管理共享对象池。
    例如:在游戏中,所有子弹享元对象由一个单例工厂管理。

    class FlyweightFactory {
        private static final FlyweightFactory INSTANCE = new FlyweightFactory();
        private final Map<String, Flyweight> pool = new HashMap<>();
    
        private FlyweightFactory() {}
    
        public static FlyweightFactory getInstance() {
            return INSTANCE;
        }
    
        public Flyweight getFlyweight(String key) {
            return pool.computeIfAbsent(key, ConcreteFlyweight::new);
        }
    }
    
  • 冲突场景
    若单例对象需要持有多个享元实例,需避免混淆两者的设计目标。
    (例如:单例的配置管理器内部使用享元优化重复配置项的存储。)


5. 总结
模式选择依据
享元模式当系统中存在大量重复对象,且可分离内部状态(共享)与外部状态(非共享)时使用。
单例模式当需要确保全局唯一实例,或控制对共享资源(如线程池、配置)的访问时使用。
  • 关键区别:享元模式关注对象共享,单例模式关注实例唯一性
  • 共同点:二者均可减少资源占用,但实现方式和应用场景不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值