運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對象,系統(tǒng)只使用少量的對象,而這些對象都相近,狀態(tài)變化很小,對象使用次數(shù)增多。
UML類圖如下:

其中類和對象的關(guān)系:
1. Flyweight(抽象輕量級類):聲明一個(gè)接口,通過它可以接受外來的參數(shù)(狀態(tài)),并對新狀態(tài)做出出來(作用)。
2. ConcreteFlyweight(具體輕量級類):實(shí)現(xiàn)Flyweight的接口,并為內(nèi)部狀態(tài)增加存儲空間,ConcreteFlyweight對象必須是可以共享的,它所有存儲的狀態(tài)必須是內(nèi)部的,它獨(dú)立存在于自己的環(huán)境中。
3. UnsharedConcreteFlyweight(不共享具體輕量級類):不是所有的Flyweight子類都需要包兒共享,F(xiàn)lyweight的共享不是強(qiáng)制的。在某些Flyweight的結(jié)構(gòu)層次中,UnsharedConcreteFlyweight對象通常將ConcreteFlyweight對象作為子節(jié)點(diǎn)。
4. FlyweightFactory(輕量級類工廠):創(chuàng)建并管理flyweight對象;確保享用flyweight。當(dāng)用戶請求一個(gè)flyweight時(shí),F(xiàn)lyweightFactory提供一個(gè)已創(chuàng)建的實(shí)例或者創(chuàng)建一個(gè)實(shí)例。
5. Client(客戶應(yīng)用程序):維持一個(gè)對flyweight的引用;計(jì)算或存儲一個(gè)或多個(gè)flyweight的外部狀態(tài)。
典型應(yīng)用的順序圖如圖:

客戶初次從輕量級類工廠取flyweight時(shí),輕量級類工廠創(chuàng)建一個(gè)新的具體flyweight對象,并且保存起來,下次客戶取用時(shí),就不用重新創(chuàng)建,直接在保存池中返回。客戶負(fù)責(zé)處理flyweight的狀態(tài)。
潛在的,每個(gè)字符都被大量的采用,因此共享這些字符對象將會(huì)節(jié)省大量的存儲空間。文檔編輯器的UML類圖如下:

代碼
//Flyweight工廠
class CharacterFactotry
{
private Hashtable characters = new Hashtable();
public Character GetCharacter(char key)
{
//在初始化的Hashtable中取出字符
Character character = (Character)characters[key];
//如果取出的字符為null,初始化它
if (character == null)
{
switch (key)
{
case 'A':
character = new CharacterA();
break;
case 'B':
character = new CharacterB();
break;
case 'Z':
character = new CharacterZ();
break;
}
characters.Add(key, character);
}
return character;
}
}
//Flyweight
abstract class Character
{
protected char symbol;
protected int width;
protected int height;
protected int ascent;
protected int descent;
protected int pointSize;
public abstract void Draw(int pointSize);
}
class CharacterA : Character
{
public CharacterA()
{
this.symbol = 'A';
this.height = 100;
this.width = 120;
this.ascent = 70;
this.descent = 0;
}
public override void Draw(int pointSize)
{
this.pointSize = pointSize;
Console.WriteLine(this.symbol);
}
}
class CharacterB : Character
{
public CharacterB()
{
this.symbol = 'B';
this.height = 100;
this.width = 140;
this.ascent = 72;
this.descent = 0;
}
public override void Draw(int pointSize)
{
this.pointSize = pointSize;
Console.WriteLine(this.symbol);
}
}
class CharacterZ : Character
{
public CharacterZ()
{
this.symbol = 'Z';
this.height = 100;
this.width = 100;
this.ascent = 68;
this.descent = 0;
}
public override void Draw(int pointSize)
{
this.pointSize = pointSize;
Console.WriteLine(this.symbol);
}
}
//客戶應(yīng)用測試
class Client
{
[STAThread]
static void Main(string[] args)
{
//用字符數(shù)組創(chuàng)造document
char[] document = { 'A', 'B', 'Z', 'Z', 'A', 'A' };
CharacterFactotry f = new CharacterFactotry();
//外部狀態(tài)
int pointSize = 12;
//為每一個(gè)字符使用一個(gè)flyweight對象
foreach (char c in document)
{
Character character = f.GetCharacter(c);
character.Draw(pointSize);
}
Console.Read();
}
}

Flyweight模式需要你認(rèn)真考慮如何能細(xì)化對象,以減少處理的對象數(shù)量,從而減少存留對象在內(nèi)存或其他存儲設(shè)備中的占用量。然而,此模式需要維護(hù)大量對象的外部狀態(tài),如果外部狀態(tài)的數(shù)據(jù)量大,傳遞、查找、計(jì)算這些惡數(shù)據(jù)會(huì)變得非常復(fù)雜。當(dāng)外部和內(nèi)部的狀態(tài)很難分清時(shí),不宜采用flyweight模式。
下面的情景很適合應(yīng)用輕量級模式:
1. 系統(tǒng)需要存在大量的對象而共享某些本質(zhì)的、不變的信息。
2. 對象可以同時(shí)用于多個(gè)環(huán)境下。
3. 在每個(gè)實(shí)例下,flyweight可以作為一個(gè)獨(dú)立的對象。
-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;