C 設計模式 享元模式

2022-07-01 20:51:11 字數 4355 閱讀 1491

什麼是享元模式?

在gof的《設計模式:可復用物件導向軟體的基礎》一書中對享元模式是這樣說的:運用共享技術有效地支援大量細粒度的物件。

就如上面說的棋子,如果每個棋子都new乙個物件,就會存在大量細粒度的棋子物件,這對伺服器的記憶體空間是一種考驗,也是一種浪費。我們都知道,比如我在2013號房間和別人下五子棋,2014號房間也有人在下五子棋,並不會因為我在2013號房間,而別人在2014號房間,而導致我們的棋子是不一樣的。這就是說,2013號房間和2014號房間的棋子都是一樣的,所有的五子棋房間的棋子都是一樣的。唯一的不同是每個棋子在不同的房間的不同棋盤的不同位置上。所以,對於棋子來說,我們不用放乙個棋子就new乙個棋子物件,只需要在需要的時候,去請求獲得對應的棋子物件,如果沒有,就new乙個棋子物件;如果有了,就直接返回棋子物件。這裡以五子棋為例子,進行分析,當玩家在棋盤上放入第乙個白色棋子時,此時由於沒有白色棋子,所以就new乙個白色棋子;當另乙個玩家放入第乙個黑色棋子時,此時由於沒有黑色棋子,所以就需要new乙個黑色棋子;當玩家再次放入乙個白色棋子時,就去查詢是否有已經存在的白色棋子物件,由於第一次已經new了乙個白色棋子物件,所以,現在不會再次new乙個白色棋子物件,而是返回以前new的白色棋子物件;對於黑色棋子,亦是同理;獲得了棋子物件,我們只需要設定棋子的不同棋盤位置即可。

uml類圖

flyweight:描述乙個介面,通過這個介面flyweight可以接受並作用於外部狀態;

concreteflyweight:實現flyweight介面,並為定義了一些內部狀態,concreteflyweight物件必須是可共享的;同時,它所儲存的狀態必須是內部的;即,它必須獨立於concreteflyweight物件的場景;

unsharedconcreteflyweight:並非所有的flyweight子類都需要被共享。flyweight介面使共享成為可能,但它並不強制共享。

flyweightfactory:建立並管理flyweight物件。它需要確保合理地共享flyweight;當使用者請求乙個flyweight時,flyweightfactory物件提供乙個已建立的例項,如果請求的例項不存在的情況下,就新建立乙個例項;

client:維持乙個對flyweight的引用;同時,它需要計算或儲存flyweight的外部狀態。

實現要點

根據我們的經驗,當要將乙個物件進行共享時,就需要考慮到物件的狀態問題了;不同的客戶端獲得共享的物件之後,可能會修改共享物件的某些狀態;大家都修改了共享物件的狀態,那麼就會出現物件狀態的紊亂。對於享元模式,在實現時一定要考慮到共享物件的狀態問題。那麼享元模式是如何實現的呢?

在享元模式中,有兩個非常重要的概念:內部狀態和外部狀態。

內部狀態儲存於flyweight中,它包含了獨立於flyweight場景的資訊,這些資訊使得flyweight可以被共享。而外部狀態取決於flyweight場景,並根據場景而變化,因此不可共享。使用者物件負責在必要的時候將外部狀態傳遞給flyweight。

flyweight執行時所需的狀態必定是內部的或外部的。內部狀態儲存於concreteflyweight物件之中;而外部物件則由client物件儲存或計算。當使用者呼叫flyweight物件的操作時,將該狀態傳遞給它。同時,使用者不應該直接對concreteflyweight類進行例項化,而只能從flyweightfactory物件得到concreteflyweight物件,這可以保證對它們適當地進行共享;由於共享乙個例項,所以在建立這個例項時,就可以考慮使用單例模式來進行實現。

享元模式的工廠類維護了乙個例項列表,這個列表中儲存了所有的共享例項;當使用者從享元模式的工廠類請求共享物件時,首先查詢這個例項表,如果不存在對應例項,則建立乙個;如果存在,則直接返回對應的例項。

**實現

1 #include 2 #include 3 #include 4

using

namespace

std;

56 typedef struct

pointtag

712 pointtag(int a, int

b)13

1718

bool

operator

1924

else

if (x ==other.x)

2528

29return

false;30

}31}point;

3233 typedef enum

piececolortag

34piececolor;

3839

class

cpiece

4043 piececolor getcolor()

4445

//set the external state

46void setpoint(point point)

47 point getpoint()

4849

protected:50

//internal state

51piececolor m_color;

5253

//external state

54point m_point;

55};

5657

class cgomoku : public

cpiece

5861

};62

63class

cpiecefactory

6474

else

7583}84

if (ppiece ==null)

8589}90

return

ppiece;

91}

9293 ~cpiecefactory()

94102

}103

}104

105private

:106 vectorm_vecpiece;

107};

108109

class

cchessboard

110118

else

119123

}124

125void

showallpieces()

126133

else

134137

}138

}139

140private

:142

};143

144int

main()

145180

if (ppiecefactory !=null)

181185 }

內部狀態包括棋子的顏色,外部狀態包括棋子在棋盤上的位置。最終,我們省去了多個例項物件儲存棋子顏色的空間,從而達到了空間的節約。

在上面的**中,我建立了乙個ccheseboard用於表示棋盤,棋盤類中儲存了放置的黑色棋子和白色棋子;這就相當於在外部儲存了共享物件的外部狀態;對於棋盤物件,我們是不是又可以使用享元模式呢?再設計乙個棋局類進行管理棋盤上的棋子布局,用來儲存外部狀態。對於這個,這裡不進行討論了。

優點享元模式可以避免大量非常相似物件的開銷。在程式設計時,有時需要生成大量細粒度的類例項來表示資料。如果能發現這些例項資料除了幾個引數外基本都是相同的,使用享元模式就可以大幅度地減少物件的數量。

使用場合

flyweight模式的有效性很大程度上取決於如何使用它以及在何處使用它。當以下條件滿足時,我們就可以使用享元模式了。

乙個應用程式使用了大量的物件;

完全由於使用大量的物件,造成很大的儲存開銷;

物件的大多數狀態都可變為外部狀態;

如果刪除物件的外部狀態,那麼可以用相對較少的共享物件取代很多組物件。

擴充套件之前總結了組合模式組合模式,現在回過頭來看看,享元模式就好比在組合模式的基礎上加上了乙個工廠類,進行共享控制。是的,組合模式有的時候會產生很多細粒度的物件,很多時候,我們會將享元模式和組合模式進行結合使用。

總結使用享元模式可以避免大量相似物件的開銷,減小了空間消耗;而空間的消耗是由以下幾個因素決定的:

例項物件減少的數目;

物件內部狀態的數目;物件內部狀態越多,消耗的空間也會越少;

外部狀態是計算的還是儲存的;由於外部狀態可能需要儲存,如果外部狀態儲存起來,那麼空間的節省就不會太多。

共享的flyweight越多,儲存節約也就越多,節約量隨著共享狀態的增多而增大。當物件使用大量的內部及外部狀態,並且外部狀態是計算出來的而非儲存的時候,節約量將達到最大。所以,可以使用兩種方法來節約儲存:用共享減少內部狀態的消耗;用計算時間換取對外部狀態的儲存。

同時,在實現的時候,一定要控制好外部狀態與共享物件的對應關係,比如我在**實現部分,在ccheseboard類中使用了乙個map進行彼此之間的對映,這個對映在實際開發中需要考慮的。

c 設計模式(享元模式)

good 運用共享技術有效地支援大量細粒度的物件 對於c 來說就是共用乙個記憶體塊啦,物件指標指向同乙個地方 如果乙個應用程式使用了大量的物件,而這些物件造成了很大的儲存開銷就應該考慮使用。還有就是物件的大多數狀態可以外部狀態,如果刪除物件的外部狀態,那麼可以用較少的共享物件取代多組物件,此時可以考...

C 設計模式 享元模式

ifndef flyweight h define flyweight h include include 說明 當系統中細粒度物件數量太多時,會導致執行代價過高,帶來效能下降等問題。享元模式正是為解決這一類問題而誕生的。在享元模式中通常會出現工廠模式,需要建立乙個享元工廠來負責維護乙個享元池,用於...

c 設計模式 享元模式

二 uml類圖 三 例子 四 優缺點 五 使用場景 關注類和物件的組合。繼承的概念被用來組合介面和定義組合物件,從而獲得新功能。運用共享技術來有効地支援大量細粒度物件的復用。它通過共享已經存在的物件來大幅度減少需要建立的物件數量 避免大量相似類的開銷,從而提高系統資源的利用率。能夠大幅度地減少需要例...