Flyweight
定義
:
避免大量擁有相同內容的小類別的開銷
(
如耗費記憶體
),
使大家共用一個類別
(
元類別
)
。
爲什麽使用
?
面向物件語言的原則就是一切都是物件
,
但是如果真正使用起來
,
有時物件數可能顯得很龐大
,
比如
,
文字處理軟體
,
如果以每個文字都作爲一個物件
,
幾千個字
,
物件數就是幾千
,
無疑耗費記憶體
,
那麽我們還是要
"
求同存異
",
找出這些物件群的共同點
,
設計一個元類別
,
封裝可以被共用的類別
,
另外
,
還有一些特性是取決於應用
(context),
是不可共用的
,
這也
Flyweight
中兩個重要概念內部狀態
intrinsic
和外部狀態
extrinsic
之分。
說白點 , 就是先捏一個的原始模型 , 然後隨著不同場合和環境 , 再産生各具特徵的具體模型 , 很顯然 , 在這裏需要産生不同的新物件 , 所以 Flyweight 模式中常出現 Factory 模式。 Flyweight 的內部狀態是用來共用的 ,Flyweight factory 負責維護一個 Flyweight pool( 模式池 ) 來存放內部狀態的物件。
Flyweight 模式是一個提高程式效率和性能的模式 , 會大大加快程式的運行速度。應用場合很多 : 比如你要從一個資料庫中讀取一系列字串 , 這些字串中有許多是重復的 , 那麽我們可以將這些字串儲存在 Flyweight 池 (pool) 中。
如何使用 ?
我們先從 Flyweight 抽象介面開始 :
|
public interface Flyweight { public void operation( ExtrinsicState state ); } //
用於本模式的抽象資料類型
(
自行設計
) |
下面是介面的具體實現 (ConcreteFlyweight) , 並爲內部狀態增加記憶體空間 , ConcreteFlyweight 必須是可共用的 , 它保存的任何狀態都必須是內部 (intrinsic), 也就是說 ,ConcreteFlyweight 必須和它的應用環境場合無關。
|
public class ConcreteFlyweight implements Flyweight { } |
當然 , 並不是所有的 Flyweight 具體實現子類別都需要被共用的 , 所以還有另外一種不共用的 ConcreteFlyweight:
|
public class UnsharedConcreteFlyweight implements Flyweight {
public void operation( ExtrinsicState state ) { } } |
Flyweight factory 負責維護一個 Flyweight 池 ( 存放內部狀態 ), 當用戶端請求一個共用 Flyweight 時 , 這個 factory 首先搜索池中是否已經有可適用的 , 如果有 ,factory 只是簡單返回送出這個物件 , 否則 , 創建一個新的物件 , 加入到池中 , 再返回送出這個物件池
|
public class FlyweightFactory { //Flyweight pool private Hashtable flyweights = new Hashtable(); public Flyweight getFlyweight( Object key ) { Flyweight flyweight = (Flyweight) flyweights.get(key);
if( flyweight == null ) {
return flyweight; |
至此 ,Flyweight 模式的基本框架已經就緒 , 我們看看如何呼叫 :
FlyweightFactory factory = new FlyweightFactory();
Flyweight fly1 = factory.getFlyweight( "Fred" );
Flyweight fly2 = factory.getFlyweight( "Wilma" );
......
從呼叫上看 , 好象是個純粹的 Factory 使用 , 但奧妙就在於 Factory 的內部設計上。
Flyweight
模式在
XML
等資料源中應用
我們上面已經提到
,
當大量從資料源中讀取字串
,
其中肯定有重復的
,
那麽我們使用
Flyweight
模式可以提高效率
,
以唱片
CD
爲例
,
在一個
XML
文件中
,
存放了多個
CD
的資料。
每個
CD
有三個欄位
:
1.
出片日期
(year)
2.
歌唱者姓名等資訊
(artist)
3.
唱片曲目
(title)
其中 , 歌唱者姓名有可能重復 , 也就是說 , 可能有同一個演唱者的多個不同時期 不同曲目的 CD 。我們將 " 歌唱者姓名 " 作爲可共用的 ConcreteFlyweight 。其他兩個欄位作爲 UnsharedConcreteFlyweight 。
首先看看資料源 XML 文件的內容 :
|
<?xml version="1.0"?> <collection> <cd> <cd> <cd> ....... </collection> |
雖然上面舉例
CD
只有
3
張
,CD
可看成是大量重復的小類別
,
因爲其中成分只有三個欄位
,
而且有重復的
(
歌唱者姓名
)
。
CD 就是類似上面介面 Flyweight:
|
public class CD {
private String title; |
將 " 歌唱者姓名 " 作爲可共用的 ConcreteFlyweight:
|
public class Artist {
//
內部狀態
// note that Artist is immutable.
Artist(String n){ |
再看看 Flyweight factory, 專門用來製造上面的可共用的 ConcreteFlyweight:Artist
|
public class ArtistFactory {
Hashtable pool = new Hashtable();
Artist result; |
當你有幾千張甚至更多 CD 時 ,Flyweight 模式將節省更多空間 , 共用的 flyweight 越多 , 空間節省也就越大。
本文深入探讨了享元模式的设计理念及其在实际应用中的优势。通过具体案例,详细介绍了如何利用享元模式来优化内存使用,特别是在处理大量重复数据时的表现。
1359

被折叠的 条评论
为什么被折叠?



