1. 程式人生 > 其它 >【結構型】享元模式

【結構型】享元模式

享元模式的意圖是複用物件,節省記憶體,前提是享元物件是不可變物件(不能暴露任何set()等修改內部狀態的方法)。

具體來講,當一個系統中存在大量重複物件的時候,如果這些重複的物件是不可變物件,我們就可以利用享元模式將物件設計成享元,在記憶體中只保留一份例項,供多處程式碼引用。這樣可以減少記憶體中物件的數量,起到節省記憶體的目的。實際上,不僅僅相同物件可以設計成享元,對於相似物件,我們也可以將這些物件中相同的部分(欄位)提取出來,設計成享元,讓這些大量相似物件引用這些享元。

應用:多個遊戲大廳中棋子的記憶體共享

// 享元類
public class ChessPieceUnit {
  private
int id; private String text; private Color color; public ChessPieceUnit(int id, String text, Color color) { this.id = id; this.text = text; this.color = color; } public static enum Color { RED, BLACK } // ...省略其他屬性和getter方法... } public class ChessPieceUnitFactory {
private static final Map<Integer, ChessPieceUnit> pieces = new HashMap<>(); static { pieces.put(1, new ChessPieceUnit(1, "車", ChessPieceUnit.Color.BLACK)); pieces.put(2, new ChessPieceUnit(2,"馬", ChessPieceUnit.Color.BLACK)); //...省略擺放其他棋子的程式碼... } public static ChessPieceUnit getChessPiece(int
chessPieceId) { return pieces.get(chessPieceId); } } public class ChessPiece { private ChessPieceUnit chessPieceUnit; private int positionX; private int positionY; public ChessPiece(ChessPieceUnit unit, int positionX, int positionY) { this.chessPieceUnit = unit; this.positionX = positionX; this.positionY = positionY; } // 省略getter、setter方法 } public class ChessBoard { private Map<Integer, ChessPiece> chessPieces = new HashMap<>(); public ChessBoard() { init(); } private void init() { chessPieces.put(1, new ChessPiece( ChessPieceUnitFactory.getChessPiece(1), 0,0)); chessPieces.put(1, new ChessPiece( ChessPieceUnitFactory.getChessPiece(2), 1,0)); //...省略擺放其他棋子的程式碼... } public void move(int chessPieceId, int toPositionX, int toPositionY) { //...省略... } }
View Code

利用工廠類來快取ChessPieceUnit資訊(也就是id、text、color)。通過工廠類獲取到的ChessPieceUnit就是享元。所有的ChessBoard物件共享這30個ChessPieceUnit物件(因為象棋中只有30個棋子)。在使用享元模式之前,記錄1萬個棋局,我們要建立30萬(30*1萬)個棋子的ChessPieceUnit物件。利用享元模式,我們只需要建立30個享元物件供所有棋局共享使用即可,大大節省了記憶體。

程式碼實現非常簡單,主要是通過工廠模式,在工廠類中,通過一個Map來快取已經建立過的享元物件,來達到複用的目的。