Go設計模式(17)-享元模式

享元模式主要是為了複用物件,節省記憶體。使用享元模式需要有兩個前提:

享元物件不可變:當享元模式創建出來後,它的變數和屬性不會被修改

系統中存在大量重複物件:這些重複物件可以使用同一個享元,記憶體中只存在一份,這樣會節省大量空間。當然這也是為什麼享元物件不可變的原因,因為有很多引用,變更的話會引起很多問題。

UML類圖位置:https://www。processon。com/diagraming/609b375407912943913a4c13

本文程式碼連結為:https://github。com/shidawuhen/asap/blob/master/controller/design/17flyweight。go

1。定義

1。1享元模式

享元模式

:運用共享技術有效的支援大量細粒度的物件。

UML

Go設計模式(17)-享元模式

1。2分析

享元模式主要是把系統中共同的、不變的物件抽象出來,達到共用一份的效果

抽象出的物件介面為Flyweight,ConcreteFlyweight為實際被共享的物件。UnsharedConcreteFlyweight是否存在,主要看是否有物件是無需共享的。

享元模式裡有工廠FlyweightFactory,主要是因為系統中需要的享元結構雖然確定了,但是享元的屬性不同,所以需要管理多個物件,此處使用了工廠模式。關於工廠模式可以參看這篇文章Go設計模式(7)-工廠模式。

2。使用場景

享元模式還是有很多具體使用場景的,如很多聯網類棋牌遊戲。假設有100w場象棋遊戲在同時進行,不使用享元模式的話,系統需要維護32*100w個象棋物件。但象棋的文案、顏色、規則是不變的,變的只是持有人和位置。所以將32個象棋物件抽象出來,當做享元,可以極大的節省空間,而且不會帶來成本提升。

Go設計模式(17)-享元模式

享元模式與其說是一種設計模式,不如說是一種設計理念,主要講的是抽象的能力,將相同模組提取出來,供不同模組使用

。從這個維度來說,程式碼重構中提取相同功能、單例模式等,何嘗不是另一種享元。

3。程式碼實現

寫一下象棋遊戲中對於象棋的管理吧。

package mainimport “fmt”/** * @Author: Jason Pang * @Description: 棋子類,有文案、顏色、規則,這三種不變屬性 */type Piece struct { text string color string rule string}/** * @Author: Jason Pang * @Description: 棋子資訊說明 * @receiver p * @return string */func (p *Piece) String() string { return fmt。Sprintf(“%s,顏色為%s,規則為%s”, p。text, p。color, p。rule)}/** * @Author: Jason Pang * @Description: 棋子在棋盤位置 */type Pos struct { x int64 y int64}/** * @Author: Jason Pang * @Description: 遊戲中的棋子 */type GamePiece struct { piece *Piece //棋子指標 pos Pos //棋子位置 ownerId int64 //玩家ID roomId int64 //房間ID}/** * @Author: Jason Pang * @Description: 遊戲中的棋子說明 * @receiver g * @return string */func (g *GamePiece) String() string { return fmt。Sprintf(“%s位置為(%d,%d)”, g。piece, g。pos。x, g。pos。y)}/** * @Author: Jason Pang * @Description: 棋子工廠,包含32顆棋子資訊 */type PieceFactory struct { pieces []*Piece}/** * @Author: Jason Pang * @Description: 建立棋子。棋子的資訊都是不變的 * @receiver f */func (f *PieceFactory) CreatePieces() { f。pieces = make([]*Piece, 32) f。pieces[0] = &Piece{ text: “兵”, color: “紅”, rule: “過河前只能一步一步前進,過河後只能一步一步前進或者左右移”, } f。pieces[1] = &Piece{ text: “兵”, color: “黑”, rule: “過河前只能一步一步前進,過河後只能一步一步前進或者左右移”, } //todo 建立其它棋子。此處可以使用配置檔案建立,能方便一些。系統中可以設定一個規則引擎,控制棋子運動。}/** * @Author: Jason Pang * @Description: 獲取棋子資訊 * @receiver f * @param id * @return *Piece */func (f *PieceFactory) GetPiece(id int64) *Piece { return f。pieces[id]}/** * @Author: Jason Pang * @Description: 初始化棋盤 * @param roomId * @param u1 * @param u2 */func InitBoard(roomId int64, u1 int64, u2 int64, factory *PieceFactory) { fmt。Printf(“建立房間%d,玩家為%d和%d \n”, roomId, u1, u2) fmt。Println(“初始化棋盤”) fmt。Printf(“玩家%d的棋子為 \n”, u1) piece := &GamePiece{ piece: factory。GetPiece(0), pos: Pos{1, 1}, roomId: roomId, ownerId: u1, } fmt。Println(piece) fmt。Printf(“玩家%d的棋子為 \n”, u2) piece2 := &GamePiece{ piece: factory。GetPiece(1), pos: Pos{16, 1}, roomId: roomId, ownerId: u2, } fmt。Println(piece2)}func main() { factory := &PieceFactory{} factory。CreatePieces() InitBoard(1, 66, 88, factory)}

輸出:

➜ myproject go run main。go

建立房間1,玩家為66和88

初始化棋盤

玩家66的棋子為

兵,顏色為紅,規則為過河前只能一步一步前進,過河後只能一步一步前進或者左右移位置為(1,1)

玩家88的棋子為

兵,顏色為黑,規則為過河前只能一步一步前進,過河後只能一步一步前進或者左右移位置為(16,1)

3總結

享元模式充分說明了抽象的重要性,希望大家能夠善用這種模式,最佳化系統。

最後

大家如果喜歡我的文章,可以關注我的公眾號(程式設計師麻辣燙)

我的個人部落格為:https://shidawuhen。github。io/

往期文章回顧:

招聘

位元組跳動|內推大放送

位元組跳動|今日頭條廣州服務端研發工程師內推

位元組跳動|抖音電商急招上海前端開發工程

位元組跳動|抖音電商上海資深服務端開發工程師-交易

位元組跳動|抖音電商武漢服務端(高階)開發工程師

位元組跳動|飛書大客戶產品經理內推咯

位元組跳動|抖音電商服務端技術崗位虛位以待

位元組跳動招聘專題

設計模式

Go設計模式(16)-組合模式

Go設計模式(15)-門面模式

Go設計模式(14)-介面卡模式

Go設計模式(13)-裝飾器模式

Go設計模式(12)-橋接模式

Go設計模式(11)-代理模式

Go設計模式(10)-原型模式

Go設計模式(9)-建造者模式

Go設計模式(8)-抽象工廠

Go設計模式(7)-工廠模式

Go設計模式(6)-單例模式

Go設計模式(5)-類圖符號表示法

Go設計模式(4)-程式碼編寫最佳化

Go設計模式(4)-程式碼編寫

Go設計模式(3)-設計原則

Go設計模式(2)-面向物件分析與設計

Go設計模式(1)-語法

語言

再也不怕獲取不到Gin請求資料了

一文搞懂pprof

Go工具之generate

Go單例實現方案

Go通道實現原理

Go定時器實現原理

Beego框架使用

Golang原始碼BUG追查

Gin框架簡潔版

Gin原始碼剖析

架構

分頁複選設計的坑

支付接入常規問題

限流實現2

秒殺系統

分散式系統與一致性協議

微服務之服務框架和註冊中心

淺談微服務

限流實現1

CDN請求過程詳解

常用快取技巧

如何高效對接第三方支付

演算法總結

儲存

一文搞懂MySQL資料庫分庫分表

MySQL開發規範

Redis實現分散式鎖

事務原子性、一致性、永續性的實現原理

InnoDB鎖與事務簡析

網路

HTTP2。0基礎教程

HTTPS配置實戰

HTTPS連線過程

TCP效能最佳化

工具

GoLand實用技巧

根據mysql表自動生成go struct

Markdown編輯器推薦-typora

讀書筆記

《毛選》推薦

原則

資治通鑑

敏捷革命

如何鍛鍊自己的記憶力

簡單的邏輯學-讀後感

熱風-讀後感

論語-讀後感

孫子兵法-讀後感

思考

對過去的一點回顧

對寫部落格的一些思考

晚上打119的經歷

為動員一切力量爭取勝利而鬥爭

反對自由主義

實踐論

評價自己的標準

2020部落格總結

服務端團隊假期值班方案

專案流程管理

對專案管理的一些看法

對產品經理的一些思考

關於程式設計師職業發展的思考

關於程式碼review的思考