運用共享技術有效地支持大量細粒度的對象,系統只使用少量的對象,而這些對象都相近,狀態變化很小,對象使用次數增多。
UML類圖如下:

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

客戶初次從輕量級類工廠取flyweight時,輕量級類工廠創建一個新的具體flyweight對象,并且保存起來,下次客戶取用時,就不用重新創建,直接在保存池中返回。客戶負責處理flyweight的狀態。
潛在的,每個字符都被大量的采用,因此共享這些字符對象將會節省大量的存儲空間。文檔編輯器的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);
}
}
//客戶應用測試
class Client
{
[STAThread]
static void Main(string[] args)
{
//用字符數組創造document
char[] document = { 'A', 'B', 'Z', 'Z', 'A', 'A' };
CharacterFactotry f = new CharacterFactotry();
//外部狀態
int pointSize = 12;
//為每一個字符使用一個flyweight對象
foreach (char c in document)
{
Character character = f.GetCharacter(c);
character.Draw(pointSize);
}
Console.Read();
}
}

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