設計模式學習-使用go實現享元模式
享元模式
定義
享元模式(Flyweight),運用共享技術有效的支援大量細粒度的對象。
享元模式的意圖是復用對象,節省記憶體,前提是享元對象是不可變對象。就是當一個系統中有大量的重複對象的時候,如果這些對象是不可變對象,我們就可以使用
享元模式,將這些對象設計成享元,在記憶體只保存一份,供需要的程式碼使用,這樣能減少記憶體中對象的數量,起到節省記憶體的作用。實際上,不僅僅相同對象可以設計成享元,對於相似對象,我們也可以將這些對象中相同的部分(欄位)提取出來,設計成享元,讓這些大量相似對象引用這些享元。
不可變對象是函數初始化之後,他的狀態不會改變了,也就是不會存在被修改的情況。
優點
大大減少對象的創建,降低系統的記憶體,使效率提高。
缺點
提高了系統的複雜度
適用場景
一個系統中有大量相同或者相似的對象,使用這些對象,會造成記憶體的大量消耗,這時候可以考慮使用享元模式
程式碼實現
我們都下過象棋,對於象棋一共有32枚棋子,每方各16枚。每次下棋使用的都是這32枚棋子,只是每次移動的棋子的位置。
那麼這32枚棋子就可以作為享元,每次下棋就不用重新初始化生成棋子。只需在棋盤中放置棋子的位子,下棋的時候,更改位置即可。
// ChessPieceUnit ...
type ChessPieceUnit struct {
id int
text string
color string
}
var pieces map[int]*ChessPieceUnit
func init() {
pieces = make(map[int]*ChessPieceUnit, 32)
pieces[1] = &ChessPieceUnit{
id: 1,
text: "馬",
color: "BLACK",
}
pieces[2] = &ChessPieceUnit{
id: 2,
text: "炮",
color: "BLACK",
}
// ...
}
func getChessPiece(chessPieceId int) *ChessPieceUnit {
return pieces[chessPieceId]
}
type ChessPiece struct {
chessPieceUnit *ChessPieceUnit
positionX int
positionY int
}
func newChessPiece(chessPieceId int, positionX, positionY int) *ChessPiece {
return &ChessPiece{
chessPieceUnit: getChessPiece(chessPieceId),
positionX: positionX,
positionY: positionY,
}
}
// 棋盤
type ChessBoard struct {
chessPieces map[int]*ChessPiece
}
func (cb *ChessBoard) InitChessBoard() {
cb.chessPieces = make(map[int]*ChessPiece, 32)
cb.chessPieces[1] = newChessPiece(1, 0, 1)
cb.chessPieces[2] = newChessPiece(2, 0, 2)
// ...
}
// Move 下棋
func (cb *ChessBoard) Move(chessPieceId int, positionX, positionY int) {
// TODO
}
享元模式和單例模式的區別
單例模式:一個類只能創建一個對象。
享元模式:一個類可以創建多個對象,每個對象被多處程式碼引用共享。實際上,享元模式有點類似於之前講到的單例的變體:多例。
單例對象可以是可變的。 享元對象是不可變的。
實現上差不多,不過設計意圖不同,享元模式是為了對象復用,節省記憶體,而應用多例模式是為了限制對象的個數。
參考
【文中程式碼】//github.com/boilingfrog/design-pattern-learning/tree/master/享元模式
【大話設計模式】//book.douban.com/subject/2334288/
【極客時間】//time.geekbang.org/column/intro/100039001
【享元模式】//boilingfrog.github.io/2021/11/17/使用go實現享元模式/

