享元模式
享元模式(Flyweight Pattern)主要用于減少創(chuàng)建對象的數(shù)量,以減少內存占用和提高性能。這種類型的設計模式屬于結構型模式,它提供了減少對象數(shù)量從而改善應用所需的對象結構的方式。
享元模式嘗試重用現(xiàn)有的同類對象,如果未找到匹配的對象,則創(chuàng)建新對象。我們將通過創(chuàng)建 5 個對象來畫出 20 個分布于不同位置的圓來演示這種模式。由于只有 5 種可用的顏色,所以 color 屬性被用來檢查現(xiàn)有的 Circle 對象。
介紹
意圖:運用共享技術有效地支持大量細粒度的對象。
主要解決:在有大量對象時,有可能會造成內存溢出,我們把其中共同的部分抽象出來,如果有相同的業(yè)務請求,直接返回在內存中已有的對象,避免重新創(chuàng)建。
何時使用: 1、系統(tǒng)中有大量對象。 2、這些對象消耗大量內存。 3、這些對象的狀態(tài)大部分可以外部化。 4、這些對象可以按照內蘊狀態(tài)分為很多組,當把外蘊對象從對象中剔除出來時,每一組對象都可以用一個對象來代替。 5、系統(tǒng)不依賴于這些對象身份,這些對象是不可分辨的。
如何解決:用唯一標識碼判斷,如果在內存中有,則返回這個唯一標識碼所標識的對象。
關鍵代碼:用 HashMap 存儲這些對象。
應用實例: 1、JAVA 中的 String,如果有則返回,如果沒有則創(chuàng)建一個字符串保存在字符串緩存池里面。 2、數(shù)據(jù)庫的數(shù)據(jù)池。
優(yōu)點:大大減少對象的創(chuàng)建,降低系統(tǒng)的內存,使效率提高。
缺點:提高了系統(tǒng)的復雜度,需要分離出外部狀態(tài)和內部狀態(tài),而且外部狀態(tài)具有固有化的性質,不應該隨著內部狀態(tài)的變化而變化,否則會造成系統(tǒng)的混亂。
使用場景: 1、系統(tǒng)有大量相似對象。 2、需要緩沖池的場景。
注意事項: 1、注意劃分外部狀態(tài)和內部狀態(tài),否則可能會引起線程安全問題。 2、這些類必須有一個工廠對象加以控制。
實現(xiàn)
我們將創(chuàng)建一個 Shape 接口和實現(xiàn)了 Shape 接口的實體類 Circle。下一步是定義工廠類 ShapeFactory。
ShapeFactory 有一個 Circle 的 HashMap,其中鍵名為 Circle 對象的顏色。無論何時接收到請求,都會創(chuàng)建一個特定顏色的圓。ShapeFactory 檢查它的 HashMap 中的 circle 對象,如果找到 Circle 對象,則返回該對象,否則將創(chuàng)建一個存儲在 hashmap 中以備后續(xù)使用的新對象,并把該對象返回到客戶端。
FlyWeightPatternDemo,我們的演示類使用 ShapeFactory 來獲取 Shape 對象。它將向 ShapeFactory 傳遞信息(red / green / blue/ black / white),以便獲取它所需對象的顏色。

案例一
// 1.畫圖協(xié)議
protocol Shape {
func draw()
}
// 2.實現(xiàn)協(xié)議的結構體
struct Circle: Shape {
var color: String?
var x: Int = 0
var y: Int = 0
var radius: Int = 0
init(color: String) {
self.color = color
}
mutating func setX(_ x: Int) {
self.x = x
}
mutating func setY(_ y: Int) {
self.y = y
}
func draw() {
print("Circle: Draw() [Color :\(color), x : \(x) , y :\(y) radius :\(radius)")
}
}
// 3.工廠
struct ShapeFactory {
var flyweights = Dictionary<String, Shape>()
mutating func getCircle(color: String) -> Shape {
if !flyweights.keys.contains(color) {
flyweights[color] = Circle(color:color)
}
return flyweights[color]!
}
}
案例二
)
// 1.網(wǎng)站協(xié)議
protocol Website {
func use()
}
// 2. 具體網(wǎng)站
struct ConcreateWebsite: Website {
var name: String
func use() {
print("name: \(name)")
}
}
// 3. 網(wǎng)站工廠
struct WebsiteFactory {
var flyweights = Dictionary<String, Website>()
mutating func getWebsiteCategory(_ key: String) -> Website {
if !flyweights.keys.contains(key) {
flyweights[key] = ConcreateWebsite(name: key)
}
return flyweights[key]!
}
func getWebsiteCount() -> Int {
return flyweights.count
}
}
var f = WebsiteFactory()
let wsA = f.getWebsiteCategory("產(chǎn)品展示")
wsA.use()
let wsB = f.getWebsiteCategory("產(chǎn)品展示")
wsB.use()
let wsC = f.getWebsiteCategory("博客")
wsC.use()
let wsD = f.getWebsiteCategory("博客")
wsD.use()
let wsE = f.getWebsiteCategory("博客")
wsE.use()
print("分類數(shù):\(f.getWebsiteCount())")
參考文檔: 享元模式