1、意圖
運用共享技術有效地支持大量細粒度的對象
2、動機
Flyweight模式描述瞭如何共享對象,使得可以細粒度地使用它們而無需高昂的代價。
3、適用性
Flyweight模式的有效性很大程度上取決於如何使用它以及在何處使用它。
-
一個應用程序使用了大量的對象;
-
完全由於使用了大量的對象,造成很大的存儲開銷;
-
對象的大多數狀態都可變爲外部狀態;
-
如果刪除對象的外部狀態,那麼可以用相對較少的共享對象取代很多組的對象;
-
應用程序不依賴於對象標識。由於Flyweight對象可以被共享,對於概念上明顯有別的對象,標識測試將返回真值。
4、結構
下面的對象圖說明了如何共享flyweight:
5、參與者
- Flyweight: 定義一個接口,通過這個接口Flyweight可以接受並作用於外部狀態。
- ConcreteFlyweight:實現Flyweight接口,並增加內部狀態。ConcreteFlyweight對象必須是可共享的。
- UnsharedConcreteflyweight:並非所有的Flyweight子類對象都需要被共享。flyweight接口使共享成爲可能,但它並不強制共享。
- FlyweightFactory:
- 創建並管理Flyweight對象;
- 確保合理地共享Flyweight。當用戶請求一個flyweight時,FlyweightFactory對象提供一個已創建的實例或創建一個。 - Client:維持一個對Flyweight的引用;計算或存儲一個(或多個)Flyweight對象的外部狀態。
6、協作
- Flyweight執行是所需要的狀態必定是內部的或外部的。內部狀態存儲於ConcreteFlyweight對象中,而外部狀態則由Client對象存儲或計算,當用戶調用flyweight接口時,傳遞該狀態。
- 用戶不應直接對ConcreteFlyweight類進行實例化,而只能從FlyweightFactory對象得到ConcreteFlyweight對象,這可以保證對它們適當的進行共享。
7、效果
使用Flyweight模式時,傳輸、查找(計算)外部狀態都會產生運行時的開銷,然而空間上的節省抵消了這些開銷。共享的flyweight越多,空間節省也就越大。節約量隨着共享狀態的增多而增大,當對象使用大量的內部和外部狀態,並且外部狀態時計算出來的而非存儲的時候,節約量將達到最大。
所以,可用兩種方法來節約存儲:用共享來減少內部狀態的消耗,用計算時間換取對外部狀態的存儲。
8、實現
- 識別外部狀態 該模式的可用性在很大程度上取決於是否很容易識別外部狀態並將它從對象中刪除。如果不同種類的外部狀態和共享前對象的數目一樣的話,刪除外部狀態不會降低存儲消耗。理想的情況是,外部狀態可以由一個單獨的對象結構計算得到,且該結構的存儲要求非常小。
- 管理共享對象 用戶不能直接實例化共享對象,而應通過FlyweightFactory對象查找感興趣的Flyweight對象。
共享還意味着引用計數和垃圾回收機制,然而當共享對象量很小時,可以永久保存,不需要這兩種操作。
9、相關模式
-
Flyweight模式通常和Composite模式結合起來,用共享葉節點的有向無環圖實現一個邏輯上的層次結構。
-
通常,最好用Flyweight模式實現State和Strategy對象。