设计模式-享元模式

享元模式(Flyweight Pattern)概述

定义
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享相同的对象来减少内存的使用,特别适用于对象数量庞大且相似的场景。通过共享相同的对象来减少内存的使用,并确保在需要的时候能够快速地访问和使用对象。

享元模式的核心思想是:

  • 对于相同内容的对象进行共享,避免每次都创建相同对象。
  • 通过将共享的部分提取到外部的享元池中,节省内存开销。
  • 享元模式的关键是将不可变部分(共享部分)提取到外部,避免重复存储。

享元模式的角色

  1. 享元(Flyweight):享元对象可以通过共享来降低内存的消耗。享元对象通常有两个部分:
    • 内部状态(Intrinsic State):可以被多个对象共享的部分。
    • 外部状态(Extrinsic State):对象的具体使用状态,每个对象可能不同。
  2. 具体享元(ConcreteFlyweight):实现享元接口,存储内部状态。
  3. 享元工厂(FlyweightFactory):负责管理享元对象的创建,确保共享对象的复用。
  4. 客户端(Client):使用享元对象,并维护外部状态。

示例:文字字符的共享

假设我们需要在文本编辑器中显示字符,我们不希望每个字符都创建一个独立的对象,而是共享相同字符的对象(如字母 "A" 和字母 "B")。

Java 实现代码

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

// 享元接口
interface Flyweight {
    void display(String extrinsicState);
}

// 具体享元类
class ConcreteFlyweight implements Flyweight {
    private String intrinsicState; // 内部状态

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

    @Override
    public void display(String extrinsicState) {
        System.out.println("字符: " + intrinsicState + ", 位置: " + extrinsicState);
    }
}

// 享元工厂
class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();

    public Flyweight getFlyweight(String intrinsicState) {
        if (!flyweights.containsKey(intrinsicState)) {
            flyweights.put(intrinsicState, new ConcreteFlyweight(intrinsicState));
        }
        return flyweights.get(intrinsicState);
    }

    public int getFlyweightCount() {
        return flyweights.size();
    }
}

// 客户端
public class FlyweightPatternDemo {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();

        // 获取共享对象
        Flyweight flyweight1 = factory.getFlyweight("A");
        Flyweight flyweight2 = factory.getFlyweight("B");
        Flyweight flyweight3 = factory.getFlyweight("A");

        // 显示对象,传入外部状态(如字符位置)
        flyweight1.display("位置1");
        flyweight2.display("位置2");
        flyweight3.display("位置3");

        System.out.println("享元对象的数量: " + factory.getFlyweightCount());
    }
}

输出结果

字符: A, 位置: 位置1
字符: B, 位置: 位置2
字符: A, 位置: 位置3
享元对象的数量: 2

享元模式的优点

  1. 减少内存使用:通过共享相同的对象,节省了大量的内存空间。
  2. 提高性能:避免重复创建相同的对象,减少了对象的创建和销毁的时间开销。
  3. 提高系统可扩展性:可以轻松地添加新的享元对象,不需要改变现有的代码结构。

享元模式的缺点

  1. 增加复杂度:由于享元模式通过共享对象管理状态,可能会使系统设计变得复杂。
  2. 不适用所有场景:享元模式适用于状态可以共享的对象,但如果对象状态差异较大,享元模式就不太适用。

使用场景

  1. 字符串池:Java 中的字符串池就是利用享元模式来管理相同内容的字符串对象,避免重复创建相同的字符串。
  2. 大规模的图形绘制:比如在游戏中,不同的敌人可能有相同的外观(颜色、形状等),但它们的具体位置不同,可以通过享元模式来减少内存的消耗。
  3. 文本编辑器:每个字符的显示可以看作一个享元对象,其中字符本身是共享的,而字符的位置则是外部状态。

通过享元模式,系统能够显著减少对象的创建数量和内存使用,尤其是在处理大量相似对象时,享元模式非常有效。

posted @ 2025-01-16 09:48  庞某人  阅读(54)  评论(0)    收藏  举报