設計模式之享元(FlyWeight)---對象結構型模式
1.意圖
運用共享技術有效地支持大量細粒度的對象。
2.適用性
1)一個應用程序使用了大量的對象。
2)完全由於使用大量的對象,造成很大的存儲開銷。
3)對象的大多數狀態都可變爲外部狀態。
4)如果刪除對象的外部狀態,那麼可以用相對較少的共享對象取代很多組對象。
5)應用程序不依賴於對象標識。由於 FlyWeight 對象可以被共享,對於概念上明顯有別的對象,標識測試將返回真值。
3.結構
1)結構圖如圖(F1)
2)下面的對象圖說明了如何共享Flyweight。
4.參與者
*Flyweight
---描述一個接口,通過這個接口Flyweight可以接受並作用於外部狀態。
*ConcreteFlyweight
---實現Flyweight接口,併爲內部狀態增加存儲空間。ConcreteFlyweight對象必須是可共享的。它所存儲的狀態必須是內部的;即:他必須獨立於ConcreteFlyweight對象的場景。
*UnsharedConcreteFlyweight
---並非所有的Flyweight子類都需要被共享,Flyweight接口使共享成爲可能,但他並不強制共享。在Flyweight對象結構的某些層次,UnsharedConcreteFlyweight對象通常將ConcreteFlyweight對象作爲子節點。
*FlyweightFactory
---創建並管理flyweight對象。
---確保合理的共享flyweight。當用戶請求一個Flyweight時。FlyweightFactory對象提供一個已 創建的實例或者創建一個。
*Client
---維持一個對Flyweight的引用。
---計算或存儲一個(多個) Flyweight的外部狀態。
5.協作
1)flyweight執行時所需的狀態必定是內部的或外部的。內部狀態存儲於 ConcreteFlyweight對象之中;外部對象則有Client 對象存儲或計算。當對象那個調用flyweight對象操作時,將該狀態傳遞給他。
2)用戶不直接對ConcreteFlyweight類進行實例化,而只能從FlyweightFactory對象得到ConcreteFlyweight對象,這可保證對他們適當的共享。
6.代碼示例:
/*********************************************************
*
*
*
* 下面的例子是一個文檔編輯器的例子,對字符(Charact)實現共享,* 有利於節省空間存儲.
*
* 對應關係:Flyweight---Glyph
* ConcreteFlyweight---Charact
* UnsharedConcreteFlyweight---Row,Column
* FlyweightFactory----GlyphFactory
*
*
*
***************************************************************/
class Window;
class GlyphContext;
class Font {
public:
Font(char*);
};
class BTree;
class Glyph {
public:
virtual ~Glyph();
virtual void Draw(Window*, GlyphContext&);
virtual void SetFont(Font*, GlyphContext&);
virtual Font* GetFont(GlyphContext&);
virtual void First(GlyphContext&);
virtual void Next(GlyphContext&);
virtual bool IsDone(GlyphContext&);
virtual Glyph* Current(GlyphContext&);
virtual void Insert(Glyph*, GlyphContext&);
virtual void Remove(GlyphContext&);
protected:
Glyph();
};
class Character : public Glyph {
public:
Character(char);
virtual void Draw(Window*, GlyphContext&);
private:
char _charcode;
};
class GlyphContext {
public:
GlyphContext();
virtual ~GlyphContext();
virtual void Next(int step = 1);
virtual void Insert(int quantity = 1);
virtual Font* GetFont();
virtual void SetFont(Font*, int span = 1);
private:
int _index;
BTree* _fonts;
};
void dummy () {
GlyphContext gc;
Font* times12 = new Font("Times-Roman-12");
Font* timesItalic12 = new Font("Times-Italic-12");
// ...
gc.SetFont(times12, 6);
gc.Insert(6);
gc.SetFont(timesItalic12, 6);
}
class Row {
};
class Column {
};
const int NCHARCODES = 128;
class GlyphFactory {
public:
GlyphFactory();
virtual ~GlyphFactory();
virtual Character* CreateCharacter(char);
virtual Row* CreateRow();
virtual Column* CreateColumn();
// ...
private:
Character* _character[NCHARCODES];
};
GlyphFactory::GlyphFactory () {
for (int i = 0; i < NCHARCODES; ++i) {
_character[i] = 0;
}
}
Character* GlyphFactory::CreateCharacter (char c) {
if (!_character[c]) {
_character[c] = new Character(c);
}
return _character[c];
}
、
Row* GlyphFactory::CreateRow () {
return new Row;
}
Column* GlyphFactory::CreateColumn () {
return new Column;
}
//附: 想起來挺簡單的,可這個模式要實現真不會.