?????? GoF
《設計模式》中說道:運用共享技術有效的支持大量細粒度的對象。
?????? Flyweight
模式的結構大概是這樣的:
??????
(這張圖是按照我的理解畫出來的,如果有不對的地方還請幫我指正,謝謝),從圖上可以看出
Flyweight
模式是將相同的對象存為一個,就是在
FlyweightFactory
中對于實例化對象的判斷。這樣,客戶代碼即使是調用
1000000
個對象,如果這些對象的種類只有一個的話,對于內存的分配上也只是分配了一個對象的空間。但是有一點我想要注意:就是對于引用對象來說,這樣做,如果其中某一個對象發生變化,那么同類中的所有對象也會隨之變化。
??????
來看看程序,定義一個場景:有一個汽車類型,客戶程序要實例化
1000
個,實例化后查看一下內存分配情況。
??????
普通的面向對象方式:
??????
class
Class1
??? {
??????? [STAThread]
???????
static
void
??????? {
??????????? Console.WriteLine("
實例化前:"
+ GC.GetTotalMemory(false));
??????????? ArrayList list = new ArrayList(1000);
???????????
for(int i = 0;i < 1000;i++)
??????????? {
??????????????? Car car = new Car("
??????????????? list.Add(car);
??????????? }
??????????? Console.WriteLine("
實例化后:"
+ GC.GetTotalMemory(false));
??????????? Console.Read();
??????? }
??? }
??????
public
class Car
??? {
???????
private
string body;
???????
private
string wheel;
???????
private
string engine;
???????
private
string brand;
???????
private
string color;??
???????
public
string Body
??????? {
???????????
get{return body;}
???????????
set{body = value;}
??????? }
???????
public
string Wheel
??????? {
???????????
get{return wheel;}
???????????
set{wheel = value;}
??????? }
???????
public
string Engine
??????? {
???????????
get{return engine;}
???????????
set{engine = value;}
??????? }
???????
public
string Brand
??????? {
???????????
get{return brand;}
???????????
set{brand = value;}
??????? }
???????
public
string Color
??????? {
???????????
get{return color;}
???????????
set{color = value;}
??????? }
???????
public Car(string body,string wheel,string engine,string brand,string color)
???
??? {
??????????? Body = body;
??????????? Wheel = wheel;
??????????? Engine = engine;
??????????? Brand = brand;
??????????? Color = color;
??????? }
??? }
???
內存分配情況如下:
實例化前:
16384
實例化后:
65536
??????
然后再用
Flyweight
模式方式程序做一下比較:
??????
class
Class1
??? {
??????? [STAThread]
???????
static
void
??????? {
??????????? Console.WriteLine("
實例化前:"
+ GC.GetTotalMemory(false));
??????????? ArrayList list = new ArrayList(1000);
???????????
for(int i = 0;i < 1000;i++)
??????????? {
??????????????? FlyWeightCar car = FlyWeightFactory.CreateInit("
??????????????? list.Add(car);
??????????? }
??????????? Console.WriteLine("
實例化后:"
+ GC.GetTotalMemory(false));
??????????? Console.Read();
??????? }
??? }
public
class FlyWeightFactory
??? {
???????
private
static FlyWeightCar car;
???????
private
static Hashtable table = new Hashtable();
???????
public
static FlyWeightCar CreateInit(string body,string wheel,string engine,string brand,string color)
??????? {
???????????
if(table[brand] != null)
??????????? {
??????????????? car = (FlyWeightCar)table[brand];
??????????? }
???????????
else
??????????? {
??????????????? car = new FlyWeightCar();
??????????????? car.Brand = brand;
??????????????? car.CarBody = new CarBody(body,wheel,engine,color);
??????????????? table.Add(brand,car);
??????????? }
???????????
return car;
??????? }
??? }
???
public
class FlyWeightCar
??? {
???????
private
string brand;
???????
public
string Brand
??????? {
???????????
get
??????????? {
???????????????
return brand;
??????????? }
???????????
set
??????????? {
??????????????? brand = value;
??????????? }
??????? }
???????
private CarBody carbody;
???????
public CarBody CarBody
??????? {
???????????
get
??????????? {
???????????????
return carbody;
??????????? }
???????????
set
??????????? {
???????????????
this.carbody = value;
??????????? }
??????? }
??? }
???
public
class CarBody
??? {
???????
private
string body;
???????
private
string wheel;
???????
private
string engine;
???????
private
string color;??
???????
public
string Body
??????? {
???????????
get{return body;}
???????????
set{body = value;}
??????? }
???????
public
string Wheel
??????? {
???????????
get{return wheel;}
???????????
set{wheel = value;}
??????? }
???????
public
string Engine
??????? {
???????????
get{return engine;}
???????????
set{engine = value;}
??????? }
???????
public
string Color
??????? {
???????????
get{return color;}
???????????
set{color = value;}
??????? }
???????
public CarBody(string body,string wheel,string engine,string color)
??????? {
??????????? Body = body;
??????????? Wheel = wheel;
??????????? Engine = engine;
??????????? Color = color;
??????? }
??? }
???
內存分配情況:
實例化前:
16384
實例化后:
40960
??????
從數字上不難看出內存分配的容量節省了不少,而且隨著數量的增加,差距會更大,當然我也測試了一下數量減少的情況,當我實例化
100
個對象是結果是普通方式的內存分配更小一些,所以,在使用時,我們一定要對所實例化對象的個數進行評估,否則的話會適得其反。
?????? Flyweight
模式的幾個要點:
?????? 1
、面向對象很好的解決了抽象性的問題,但是作為一個運行在機器中的程序實體,我們需要考慮對象的代價問題。
Flyweight
設計模式主要解決面向對象的代價問題,一般不觸及面向對象的抽象性問題。
2
、
Flyweight
采用對象共享的做法來降低系統中對象的個數,從而降低細粒度對象給系統帶來的內存壓力。在具體實現方面,要注意對象的狀態處理。
3 、對象的數量太大從而導致對象內存開銷加大(這個數量要經過評估,而不能憑空臆斷)