享元模式(结构型)

目录

一、前言

二、享元模式

三、总结


一、前言

享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少大量细粒度对象的内存占用。它通过共享尽可能多的相同数据来节约内存空间。

享元模式由以下角色组成:

Flyweight(享元):

一个接口或抽象类,定义了对象的外部状态和内部状态的方法

ConcreteFlyweight(具体享元):

实现享元接口的具体类,包含享元对象的内部状态

UnsharedConcreteFlyweight(非享元):

不需要共享的对象

FlyweightFactory(享元工厂):

创建和管理享元对象,确保共享的享元对象被正确地使用

整个享元模式的结构图:

二、享元模式

我们可以以围棋为例,围棋坐标是19*19=361,围棋只有两种颜色,黑色和白色,有很多棋子,此时我们可以利用享元模式,所有黑棋共享一个对象,所有白棋共享一个对象,棋子格子的位置不同,因此位置可以设置为不共享的对象。

首先创建围棋享元接口类GoPiece.class:

java 复制代码
/**
 * @Author dengyifan
 * @create 2024/7/24 14:26
 * @description 享元接口
 */
public interface GoPiece {
    String getColor();

    void place(int x, int y);
}

再创建黑棋对象BlackPiece.class:

java 复制代码
/**
 * @Author dengyifan
 * @create 2024/7/24 14:26
 * @description 具体享元类,黑棋
 */
public class BlackPiece implements GoPiece{
    private final String color = "Black";

    @Override
    public String getColor() {
        return color;
    }

    @Override
    public void place(int x, int y) {
        System.out.println("棋子:" + color + ",位置信息:(" + x + ", " + y + ")");
    }
}

白棋对象WhitePiece.class:

java 复制代码
/**
 * @Author dengyifan
 * @create 2024/7/24 14:26
 * @description 具体享元类,白棋
 */
public class WhitePiece implements GoPiece{
    private final String color = "White";

    @Override
    public String getColor() {
        return color;
    }


    @Override
    public void place(int x, int y) {
        System.out.println("棋子:" + color + ",位置信息:(" + x + ", " + y + ")");
    }
}

编写享元工厂GoPieceFactory.class:

java 复制代码
import java.util.HashMap;
import java.util.Map;

/**
 * @Author dengyifan
 * @create 2024/7/24 14:26
 * @description 享元工厂
 */
public class GoPieceFactory {
    private static final Map<String, GoPiece> pieceMap = new HashMap<>();

    public static GoPiece getPiece(String color) {
        GoPiece piece = pieceMap.get(color);
        if (piece == null) {
            if (color.equalsIgnoreCase("Black")) {
                piece = new BlackPiece();
            } else if (color.equalsIgnoreCase("White")) {
                piece = new WhitePiece();
            }
            pieceMap.put(color, piece);
        }
        return piece;
    }
}

棋盘类BoardPosition.class:

java 复制代码
/**
 * @Author dengyifan
 * @create 2024/7/24 14:29
 * @description 棋盘位置类,包含享元对象和位置,共享GoPiece对象,以及不共享的x、y位置信息
 */
public class BoardPosition {
    private final int size;
    private final GoPiece[][] board;

    public BoardPosition(int size) {
        this.size = size;
        this.board = new GoPiece[size][size];
    }

    public void placePiece(String color, int x, int y) {
        GoPiece piece = GoPieceFactory.getPiece(color);
        board[x][y] = piece;
        piece.place(x, y);
    }

    public void printBoard() {
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (board[i][j] != null) {
                    System.out.print(board[i][j].getColor().charAt(0) + " ");
                } else {
                    System.out.print(". ");
                }
            }
            System.out.println();
        }
    }

    public GoPiece getPieceAt(int x, int y) {
        return board[x][y];
    }
}

客户端调用类:

java 复制代码
/**
 * @Author dengyifan
 * @create 2024/7/24 14:27
 * @description
 */
public class Client {
    public static void main(String[] args) {
        BoardPosition board = new BoardPosition(19);

        board.placePiece("Black", 1, 2);
        board.placePiece("White", 2, 3);
        board.placePiece("Black", 3, 4);
        board.placePiece("White", 4, 5);

        board.printBoard();

        GoPiece piece1 = board.getPieceAt(1, 2);
        GoPiece piece2 = board.getPieceAt(2, 3);
        GoPiece piece3 = board.getPieceAt(3, 4);
        GoPiece piece4 = board.getPieceAt(4, 5);

        System.out.println("棋子1和棋子3: " + (piece1 == piece3));
        System.out.println("棋子2和棋子4: " + (piece2 == piece4));
    }
}

运行结果:

三、总结

优点与缺点

优点:

减少对象数量:

通过共享技术可以有效减少内存中的对象数量,从而提高系统的性能

节约内存:

共享的享元对象能够极大地节约内存空间

缺点:

复杂性增加:

系统中引入了享元工厂和共享机制,增加了系统的复杂性

非共享对象:

并不是所有的对象都适合使用享元模式,对于那些包含大量不变数据的对象,享元模式才有明显的优势

应用场景:

文本编辑器:

在文本编辑器中,每个字符可以看作是一个对象。如果文档非常大,这些字符对象将占用大量内存。使用享元模式,可以将相同字符的对象共享起来,显著减少内存消耗

图形系统:

在图形系统中,经常需要绘制大量相同或相似的图形元素,如点、线、圆等。通过享元模式,可以将相同的图形对象共享,以节约内存

数据库连接池:

在数据库应用中,创建和销毁数据库连接的开销很大。使用享元模式,可以创建一个数据库连接池,所有的数据库连接都从池中获取和释放,从而提高性能和资源利用率

游戏开发:

在游戏开发中,大量的游戏对象(如树木、建筑物、NPC等)需要频繁使用。使用享元模式,可以将相同类型的游戏对象共享,从而减少内存占用,提高游戏性能

相关推荐
晨米酱9 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机14 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机15 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机15 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机15 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤15 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤2 天前
工厂模式
设计模式