目录
一、前言
二、享元模式
三、总结
一、前言
享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少大量细粒度对象的内存占用。它通过共享尽可能多的相同数据来节约内存空间。
享元模式由以下角色组成:
Flyweight(享元):
一个接口或抽象类,定义了对象的外部状态和内部状态的方法
ConcreteFlyweight(具体享元):
实现享元接口的具体类,包含享元对象的内部状态
UnsharedConcreteFlyweight(非享元):
不需要共享的对象
FlyweightFactory(享元工厂):
创建和管理享元对象,确保共享的享元对象被正确地使用
整个享元模式的结构图:
二、享元模式
我们可以以围棋为例,围棋坐标是19*19=361,围棋只有两种颜色,黑色和白色,有很多棋子,此时我们可以利用享元模式,所有黑棋共享一个对象,所有白棋共享一个对象,棋子格子的位置不同,因此位置可以设置为不共享的对象。
首先创建围棋享元接口类GoPiece.class:
/*** @Author dengyifan* @create 2024/7/24 14:26* @description 享元接口*/
public interface GoPiece {String getColor();void place(int x, int y);
}
再创建黑棋对象BlackPiece.class:
/*** @Author dengyifan* @create 2024/7/24 14:26* @description 具体享元类,黑棋*/
public class BlackPiece implements GoPiece{private final String color = "Black";@Overridepublic String getColor() {return color;}@Overridepublic void place(int x, int y) {System.out.println("棋子:" + color + ",位置信息:(" + x + ", " + y + ")");}
}
白棋对象WhitePiece.class:
/*** @Author dengyifan* @create 2024/7/24 14:26* @description 具体享元类,白棋*/
public class WhitePiece implements GoPiece{private final String color = "White";@Overridepublic String getColor() {return color;}@Overridepublic void place(int x, int y) {System.out.println("棋子:" + color + ",位置信息:(" + x + ", " + y + ")");}
}
编写享元工厂GoPieceFactory.class:
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:
/*** @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];}
}
客户端调用类:
/*** @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等)需要频繁使用。使用享元模式,可以将相同类型的游戏对象共享,从而减少内存占用,提高游戏性能