结构型模式-亨元模式

定义:

        享元模式(Flyweight Pattern)是池技术的重要实现方式,其定义如下:Use sharing to support large numbers of fine-grained objects efficiently.(使用共享对象可有效地支持大量的细 粒度的对象。)

结构型模式-亨元模式_第1张图片

享元模式通用类图

        亨元设计模式的核心思想是对象共享与状态分离。通过将对象的内部状态提取并共享,减少相同对象的重复创建,降低内存消耗;同时将外部状态与对象分离,由客户端负责管理,使得少量的亨元对象可以在不同场景下被重复使用,从而提高系统性能和资源利用率。

角色:

享元模式包含以下几个核心角色:

1、抽象亨元(Flyweight)

        抽象亨元定义了一个接口,用于接收外部状态并执行相应的操作。所有具体亨元类都必须实现该接口,确保客户端可以以统一的方式操作不同的亨元对象。

2、具体亨元(Concrete Flyweight)

        具体亨元是抽象亨元的实现类,它包含了对象的内部状态,并实现了抽象亨元接口中定义的方法。具体亨元对象可以被共享,在不同的场景中重复使用。

3、亨元工厂(Flyweight Factory)

        亨元工厂负责创建和管理亨元对象。它维护一个亨元对象池(通常使用集合实现),当客户端请求亨元对象时,工厂会先检查对象池中是否存在符合条件的对象,如果存在则直接返回,否则创建一个新的亨元对象并放入池中,以供后续复用。

4、客户端(Client)

        客户端负责创建和维护外部状态,并调用亨元工厂获取亨元对象,将外部状态传递给亨元对象进行操作。客户端不直接创建具体亨元对象,而是通过亨元工厂获取共享的亨元对象。​

代码示例:

        以围棋游戏为例,围棋棋盘上有大量的黑白棋子,棋子的颜色(内部状态)是固定的,而棋子在棋盘上的位置(外部状态)会不断变化。

// 抽象亨元:棋子接口

public interface ChessPiece {

    void display(int x, int y);

}

// 具体亨元:黑子

public public class BlackChessPiece implements ChessPiece {

    @Override

    public void display(int x, int y) {

        System.out.println("在 (" + x + ", " + y + ") 位置显示黑子");

    }

}

// 具体亨元:白子

public class WhiteChessPiece implements ChessPiece {

    @Override

    public void display(int x, int y) {

        System.out.println("在 (" + x + ", " + y + ") 位置显示白子");

    }

}

// 亨元工厂

public class ChessPieceFactory {

    private static final java.util.HashMap pieces = new java.util.HashMap<>();



    public static ChessPiece getChessPiece(String color) {

        if (!pieces.containsKey(color)) {

            if ("black".equals(color)) {

                pieces.put(color, new BlackChessPiece());

            } else if ("white".equals(color)) {

                pieces.put(color, new WhiteChessPiece());

            }

        }

        return pieces.get(color);

    }

}

// 客户端代码

public class FlyweightPatternClient {

    public static void main(String[] args) {

        ChessPiece blackPiece1 = ChessPieceFactory.getChessPiece("black");

        blackPiece1.display(1, 1);



        ChessPiece blackPiece2 = ChessPieceFactory.getChessPiece("black");

        blackPiece2.display(2, 2);



        ChessPiece whitePiece = ChessPieceFactory.getChessPiece("white");

        whitePiece.display(3, 3);



        System.out.println("blackPiece1 和 blackPiece2 是否相同: " + (blackPiece1 == blackPiece2));

    }

}

优点 :

1、减少内存占用:通过共享对象的内部状态,避免了相同对象的重复创建,大大减少了内存消耗,提高了系统的资源利用率。

2、提高性能:由于减少了对象的创建和销毁操作,系统在处理大量相似对象时,响应速度更快,性能得到显著提升。

3、便于维护:将对象的内部状态和外部状态分离,使得代码结构更加清晰,内部状态的修改不会影响外部状态,降低了维护成本。


缺点:

1、增加系统复杂度:亨元模式引入了亨元工厂、抽象亨元等概念,需要对对象的状态进行细致划分,增加了系统的设计和实现复杂度,尤其是在处理复杂对象时,理解和维护代码的难度较大。

2、外部状态管理复杂:客户端需要负责管理和传递外部状态,增加了客户端代码的复杂性。如果外部状态管理不当,可能会导致错误的结果或性能问题。

3、不适用于所有场景:亨元模式只适用于存在大量相似对象且对象状态可分离的场景,对于对象差异较大、无法共享内部状态的情况,使用亨元模式反而会增加系统的负担。


使用场景: 

(一)系统存在大量相似对象

        当系统中需要创建大量相似对象,且这些对象的创建和销毁会消耗较多资源时,亨元模式可以通过对象复用减少资源消耗。例如,地图应用中的大量图标、游戏中的大量相同类型的角色等。

(二)对象可分为内部状态和外部状态

        如果对象的属性可以清晰地分为内部状态和外部状态,且内部状态可以共享,外部状态可以由客户端动态传入,那么适合使用亨元模式。如文档编辑中的字符样式、图形绘制中的形状属性等。

(三)对内存占用敏感的场景

        在内存资源有限的环境中,如移动设备应用开发、嵌入式系统开发等,亨元模式通过对象共享可以有效降低内存占用,提升系统性能。

        亨元设计模式通过对象共享和状态分离的巧妙设计,为处理大量相似对象提供了高效的解决方案,在优化内存占用和提升系统性能方面具有显著优势。然而,其复杂的结构和外部状态管理要求也限制了它的适用范围。在实际开发中,当遇到符合适用场景的需求时,合理运用亨元模式能够让代码更加高效和优雅。同时,我们也要谨慎评估其带来的复杂度,确保在提升性能的同时,不影响系统的可维护性和稳定性。

你可能感兴趣的:(算法)