设计模式--享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享大量细粒度的对象来减少内存消耗。这个模式的核心思想是把对象的状态分为内在状态和外在状态,其中内在状态是可以共享的,而外在状态是需要独立维护的。

享元模式的结构

享元模式主要包含以下几个部分:

  1. 享元接口(Flyweight Interface):定义了具体享元类需要实现的方法。这些方法主要用于操作享元对象的内在状态。

  2. 具体享元类(Concrete Flyweight):实现享元接口,并存储可以共享的内在状态。

  3. 非共享享元类(Unshared Flyweight):并不是所有的享元对象都可以共享,对于那些不能共享的享元对象,可以通过这个类来实现。

  4. 享元工厂类(Flyweight Factory):负责创建和管理享元对象,并确保合理地共享这些对象。

  5. 客户端(Client):使用享元模式的类。客户端需要将外在状态传递给享元对象。

享元模式的实现

以下是一个简单的享元模式示例,用于管理和共享一些图形对象,如圆形。

java 复制代码
// 享元接口
interface Shape {
    void draw(String color);
}

// 具体享元类
class Circle implements Shape {
    private String intrinsicState; // 内在状态,可以共享
    private String extrinsicState; // 外在状态,每个对象独有

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

    @Override
    public void draw(String color) {
        this.extrinsicState = color;
        System.out.println("Drawing Circle with color: " + color + " and intrinsic state: " + intrinsicState);
    }
}

// 享元工厂类
class ShapeFactory {
    private static final Map<String, Shape> circleMap = new HashMap<>();

    public static Shape getCircle(String intrinsicState) {
        Circle circle = (Circle) circleMap.get(intrinsicState);

        if (circle == null) {
            circle = new Circle(intrinsicState);
            circleMap.put(intrinsicState, circle);
            System.out.println("Creating circle with intrinsic state: " + intrinsicState);
        }
        return circle;
    }
}

// 客户端
public class FlyweightPatternDemo {
    public static void main(String[] args) {
        Shape circle1 = ShapeFactory.getCircle("Shared State 1");
        circle1.draw("Red");

        Shape circle2 = ShapeFactory.getCircle("Shared State 1");
        circle2.draw("Green");

        Shape circle3 = ShapeFactory.getCircle("Shared State 2");
        circle3.draw("Blue");
    }
}

在这个示例中,Circle 类实现了 Shape 接口,并包含了内在状态(intrinsicState)和外在状态(extrinsicState)。ShapeFactory 类通过管理一个 HashMap 来共享 Circle 对象。客户端通过 ShapeFactory 获取 Circle 对象,并传递外在状态来绘制图形。

对象的状态分为内在状态和外在状态

将对象的状态分为内在状态和外在状态是享元模式的核心概念之一。内在状态是对象内部固有的、不随环境改变的状态,而外在状态是依赖于环境、可以在对象外部改变的状态。

为了更好地理解这个概念,我们可以通过一个例子来解释。

示例:围棋棋子

假设我们要实现一个围棋游戏,其中有许多棋子。这些棋子只有黑白两种颜色,但每个棋子的位置(行和列)是不同的。我们可以通过享元模式来共享棋子的颜色(内在状态),而位置(外在状态)则由客户端提供。

java 复制代码
// 享元接口
interface GoPiece {
    void place(int row, int col);
}

// 具体享元类
class GoPieceImpl implements GoPiece {
    private String color; // 内在状态

    public GoPieceImpl(String color) {
        this.color = color;
    }

    @Override
    public void place(int row, int col) {
        System.out.println("Placing " + color + " piece at (" + row + ", " + col + ")");
    }
}

// 享元工厂类
class GoPieceFactory {
    private static final Map<String, GoPiece> pieces = new HashMap<>();

    public static GoPiece getGoPiece(String color) {
        GoPiece piece = pieces.get(color);
        if (piece == null) {
            piece = new GoPieceImpl(color);
            pieces.put(color, piece);
            System.out.println("Creating " + color + " piece.");
        }
        return piece;
    }
}

// 客户端
public class FlyweightPatternDemo {
    public static void main(String[] args) {
        GoPiece blackPiece1 = GoPieceFactory.getGoPiece("Black");
        blackPiece1.place(1, 1);

        GoPiece blackPiece2 = GoPieceFactory.getGoPiece("Black");
        blackPiece2.place(2, 2);

        GoPiece whitePiece1 = GoPieceFactory.getGoPiece("White");
        whitePiece1.place(1, 2);

        GoPiece whitePiece2 = GoPieceFactory.getGoPiece("White");
        whitePiece2.place(2, 1);
    }
}

在这个示例中:

  1. 内在状态 :棋子的颜色(color)是可以共享的,这个状态是固定的,不会因为棋子的位置而改变。因此,我们将颜色设为内在状态。
  2. 外在状态 :棋子的行和列(rowcol)是随时变化的,这个状态取决于棋子在棋盘上的具体位置。因此,我们将位置设为外在状态,由客户端在使用棋子时传递。

在享元模式中,通过将内在状态和外在状态分离,我们可以显著减少内存消耗。在上述示例中,我们只创建了两个享元对象(黑棋子和白棋子),即使我们在不同位置放置了多个棋子,也只是复用这两个享元对象。

享元模式的优缺点

优点

  1. 减少内存消耗:通过共享细粒度对象,可以显著减少内存使用,适用于大量重复对象的场景。
  2. 提高性能:由于减少了对象的创建和销毁,可以提高系统的性能。

缺点

  1. 复杂性增加:引入享元模式后,系统的复杂性增加,需要额外的代码来管理共享对象。
  2. 适用场景有限:享元模式并不适用于所有场景,只有在有大量细粒度对象需要共享时才适用。

适用场景

享元模式主要适用于以下场景:

  1. 系统中有大量相似对象,造成了内存的高消耗。
  2. 大部分对象的状态是可以外部化的,可以通过外在状态来区分对象。
  3. 对象的内在状态是相对稳定且不变的。

通过享元模式,可以在保证系统性能的前提下,有效地减少内存的使用,提高系统的可扩展性。

相关推荐
鱼跃鹰飞1 小时前
设计模式系列:工厂模式
java·设计模式·系统架构
老蒋每日coding8 小时前
AI Agent 设计模式系列(十九)—— 评估和监控模式
人工智能·设计模式
会员果汁9 小时前
23.设计模式-解释器模式
设计模式·解释器模式
「QT(C++)开发工程师」16 小时前
C++设计模式
开发语言·c++·设计模式
茶本无香17 小时前
设计模式之七—装饰模式(Decorator Pattern)
java·设计模式·装饰器模式
漂洋过海的鱼儿1 天前
设计模式——EIT构型(三)
java·网络·设计模式
老蒋每日coding2 天前
AI Agent 设计模式系列(十八)—— 安全模式
人工智能·安全·设计模式
老蒋每日coding2 天前
AI Agent 设计模式系列(十六)—— 资源感知优化设计模式
人工智能·设计模式·langchain
老蒋每日coding2 天前
AI Agent 设计模式系列(十七)—— 推理设计模式
人工智能·设计模式
冷崖2 天前
桥模式-结构型
c++·设计模式