欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
享元模式(Flyweight Pattern)

一、 享元(Flyweight)模式

Flyweight在拳擊比賽中指最輕量級,即"蠅量級",有些作者翻譯為"羽量級"。這里使用"享元模式"更能反映模式的用意。

享元模式以共享的方式高效地支持大量的細粒度對象。享元對象能做到共享的關(guān)鍵是區分內蘊狀態(tài)(Internal State)和外蘊狀態(tài)(External State)。內蘊狀態(tài)是存儲在享元對象內部并且不會(huì )隨環(huán)境改變而改變。因此內蘊狀態(tài)并可以共享。

外蘊狀態(tài)是隨環(huán)境改變而改變的、不可以共享的狀態(tài)。享元對象的外蘊狀態(tài)必須由客戶(hù)端保存,并在享元對象被創(chuàng )建之后,在需要使用的時(shí)候再傳入到享元對象內部。外蘊狀態(tài)與內蘊狀態(tài)是相互獨立的。

享元模式的應用

享元模式在編輯器系統中大量使用。一個(gè)文本編輯器往往會(huì )提供很多種字體,而通常的做法就是將每一個(gè)字母做成一個(gè)享元對象。享元對象的內蘊狀態(tài)就是這個(gè)字母,而字母在文本中的位置和字模風(fēng)格等其他信息則是外蘊狀態(tài)。比如,字母a可能出現在文本的很多地方,雖然這些字母a的位置和字模風(fēng)格不同,但是所有這些地方使用的都是同一個(gè)字母對象。這樣一來(lái),字母對象就可以在整個(gè)系統中共享。


二、 單純享元模式的結構

在單純享元模式中,所有的享元對象都是可以共享的。單純享元模式所涉及的角色如下:

抽象享元(Flyweight)角色:此角色是所有的具體享元類(lèi)的超類(lèi),為這些類(lèi)規定出需要實(shí)現的公共接口。那些需要外蘊狀態(tài)(External State)的操作可以通過(guò)調用商業(yè)方法以參數形式傳入。

具體享元(ConcreteFlyweight)角色:實(shí)現抽象享元角色所規定的接口。如果有內蘊狀態(tài)的話(huà),必須負責為內蘊狀態(tài)提供存儲空間。享元對象的內蘊狀態(tài)必須與對象所處的周?chē)h(huán)境無(wú)關(guān),從而使得享元對象可以在系統內共享的。

享元工廠(chǎng)(FlyweightFactory)角色:本角色負責創(chuàng )建和管理享元角色。本角色必須保證享元對象可以被系統適當地共享。當一個(gè)客戶(hù)端對象調用一個(gè)享元對象的時(shí)候,享元工廠(chǎng)角色會(huì )檢查系統中是否已經(jīng)有一個(gè)復合要求的享元對象。如果已經(jīng)有了,享元工廠(chǎng)角色就應當提供這個(gè)已有的享元對象;如果系統中沒(méi)有一個(gè)適當的享元對象的話(huà),享元工廠(chǎng)角色就應當創(chuàng )建一個(gè)合適的享元對象。

客戶(hù)端(Client)角色:本角色需要維護一個(gè)對所有享元對象的引用。本角色需要自行存儲所有享元對象的外蘊狀態(tài)。


三、 單純享元模式的示意性源代碼

 

 

// Flyweight pattern -- Structural example  
using System;
using System.Collections;

// "FlyweightFactory"
class FlyweightFactory
{
  
// Fields
  private Hashtable flyweights = new Hashtable();

  
// Constructors
  public FlyweightFactory()
  
{
    flyweights.Add(
"X"new ConcreteFlyweight());
    flyweights.Add(
"Y"new ConcreteFlyweight());
    flyweights.Add(
"Z"new ConcreteFlyweight());
  }


  
// Methods
  public Flyweight GetFlyweight(string key)
  
{
    
return((Flyweight)flyweights[ key ]);
  }

}


// "Flyweight"
abstract class Flyweight
{
  
// Methods
  abstract public void Operation( int extrinsicstate );
}


// "ConcreteFlyweight"
class ConcreteFlyweight : Flyweight
{
  
private string intrinsicstate = "A";
  
// Methods
  override public void Operation( int extrinsicstate )
  
{
    Console.WriteLine(
"ConcreteFlyweight: intrinsicstate {0}, extrinsicstate {1}"
      intrinsicstate, extrinsicstate );
  }

}


/// <summary>
/// Client test
/// </summary>

public class Client
{
  
public static void Main( string[] args )
  
{
    
// Arbitrary extrisic state
    int extrinsicstate = 22;
     
    FlyweightFactory f 
= new FlyweightFactory();

    
// Work with different flyweight instances
    Flyweight fx = f.GetFlyweight("X");
    fx.Operation( 
--extrinsicstate );

    Flyweight fy 
= f.GetFlyweight("Y");
    fy.Operation( 
--extrinsicstate );

    Flyweight fz 
= f.GetFlyweight("Z");
    fz.Operation( 
--extrinsicstate );
  }

}

 


四、 復合享元模式的結構

單純享元模式中,所有的享元對象都可以直接共享。下面考慮一個(gè)較為復雜的情況,即將一些單純享元使用合成模式加以復合,形成復合享元對象。這樣的復合享元對象本身不能共享,但是它們可以分解成單純享元對象,而后者則可以共享。

復合享元模式的類(lèi)圖如下圖所示:

享元模式所涉及的角色有抽象享元角色、具體享元角色、復合享元角色、享員工廠(chǎng)角色,以及客戶(hù)端角色等。

抽象享元角色:此角色是所有的具體享元類(lèi)的超類(lèi),為這些類(lèi)規定出需要實(shí)現的公共接口。那些需要外蘊狀態(tài)(External State)的操作可以通過(guò)方法的參數傳入。抽象享元的接口使得享元變得可能,但是并不強制子類(lèi)實(shí)行共享,因此并非所有的享元對象都是可以共享的。

具體享元(ConcreteFlyweight)角色:實(shí)現抽象享元角色所規定的接口。如果有內蘊狀態(tài)的話(huà),必須負責為內蘊狀態(tài)提供存儲空間。享元對象的內蘊狀態(tài)必須與對象所處的周?chē)h(huán)境無(wú)關(guān),從而使得享元對象可以在系統內共享。有時(shí)候具體享元角色又叫做單純具體享元角色,因為復合享元角色是由單純具體享元角色通過(guò)復合而成的。

復合享元(UnsharableFlyweight)角色:復合享元角色所代表的對象是不可以共享的,但是一個(gè)復合享元對象可以分解成為多個(gè)本身是單純享元對象的組合。復合享元角色又稱(chēng)做不可共享的享元對象。

享元工廠(chǎng)(FlyweightFactoiy)角色:本角色負責創(chuàng )建和管理享元角色。本角色必須保證享元對象可以被系統適當地共享。當一個(gè)客戶(hù)端對象請求一個(gè)享元對象的時(shí)候,享元工廠(chǎng)角色需要檢查系統中是否已經(jīng)有一個(gè)符合要求的享元對象,如果已經(jīng)有了,享元工廠(chǎng)角色就應當提供這個(gè)已有的享元對象;如果系統中沒(méi)有一個(gè)適當的享元對象的話(huà),享元工廠(chǎng)角色就應當創(chuàng )建一個(gè)新的合適的享元對象。

客戶(hù)端(Client)角色:本角色還需要自行存儲所有享元對象的外蘊狀態(tài)。

注:由于復合享元模式比較復雜,這里就不再給出示意性代碼。通過(guò)將享元模式與合成模式組合在一起,可以確保復合享元中所包含的每個(gè)單純享元都具有相同的外蘊狀態(tài),而這些單純享元的內蘊狀態(tài)往往不同。該部分內容可以參考《Java與模式》第31章內容。


五、 一個(gè)咖啡攤的例子

在這個(gè)咖啡攤(CoffeeStall)所使用的系統里,有一系列的咖啡"風(fēng)味(Flavor)"??腿说綌偽簧腺徺I(mǎi)咖啡,所有的咖啡均放在臺子上,客人自己拿到咖啡后就離開(kāi)攤位??Х扔袃忍N狀態(tài),也就是咖啡的風(fēng)味;咖啡沒(méi)有環(huán)境因素,也就是說(shuō)沒(méi)有外蘊狀態(tài)。如果系統為每一杯咖啡都創(chuàng )建一個(gè)獨立的對象的話(huà),那么就需要創(chuàng )建出很多的細小對象來(lái)。這樣就不如把咖啡按照種類(lèi)(即"風(fēng)味")劃分,每一種風(fēng)味的咖啡只創(chuàng )建一個(gè)對象,并實(shí)行共享。

使用咖啡攤主的語(yǔ)言來(lái)講,所有的咖啡都可按"風(fēng)味"劃分成如Capucino、Espresso等,每一種風(fēng)味的咖啡不論賣(mài)出多少杯,都是全同、不可分辨的。所謂共享,就是咖啡風(fēng)味的共享,制造方法的共享等。因此,享元模式對咖啡攤來(lái)說(shuō),就意味著(zhù)不需要為每一份單獨調制。攤主可以在需要時(shí),一次性地調制出足夠一天出售的某一種風(fēng)味的咖啡。

很顯然,這里適合使用單純享元模式。系統的設計如下:

 

 

using System;
using System.Collections;

public abstract class Order
{
  
// 將咖啡賣(mài)給客人
  public abstract void Serve();
  
// 返回咖啡的名字
  public abstract string GetFlavor();
}


public class Flavor : Order
{
  
private string flavor;

  
// 構造函數,內蘊狀態(tài)以參數方式傳入
  public Flavor(string flavor)
  
{
    
this.flavor = flavor;
  }


  
// 返回咖啡的名字
  public override string GetFlavor()
  
{
    
return this.flavor;
  }


  
// 將咖啡賣(mài)給客人
  public override void Serve()
  
{
    Console.WriteLine(
"Serving flavor " + flavor);
  }

}


public class FlavorFactory
{
  
private Hashtable flavors = new Hashtable();

  
public Order GetOrder(string key)
  
{
    
if(! flavors.ContainsKey(key))
      flavors.Add(key, 
new Flavor(key));

        
return ((Order)flavors[key]);
  }


  
public int GetTotalFlavorsMade()
  
{
    
return flavors.Count;
  }

}


public class Client
{
  
private static FlavorFactory flavorFactory;
  
private static int ordersMade = 0;

  
public static void Main( string[] args )
  
{
    flavorFactory 
= new FlavorFactory();

    TakeOrder(
"Black Coffee");
    TakeOrder(
"Capucino");
    TakeOrder(
"Espresso");
    TakeOrder(
"Capucino");
    TakeOrder(
"Espresso");
    TakeOrder(
"Black Coffee");
    TakeOrder(
"Espresso");
    TakeOrder(
"Espresso");
    TakeOrder(
"Black Coffee");
    TakeOrder(
"Capucino");
    TakeOrder(
"Capucino");
    TakeOrder(
"Black Coffee");

    Console.WriteLine(
"\nTotal Orders made: " + ordersMade);

    Console.WriteLine(
"\nTotal Flavor objects made: " + 
      flavorFactory.GetTotalFlavorsMade());
  }


  
private static void TakeOrder(string aFlavor)
  
{
    Order o 
= flavorFactory.GetOrder(aFlavor);
    
// 將咖啡賣(mài)給客人
    o.Serve();

    ordersMade
++;
  }

}

 


六、 咖啡屋的例子

在前面的咖啡攤項目里,由于沒(méi)有供客人坐的桌子,所有的咖啡均沒(méi)有環(huán)境的影響。換言之,咖啡僅有內蘊狀態(tài),也就是咖啡的種類(lèi),而沒(méi)有外蘊狀態(tài)。

下面考慮一個(gè)規模稍稍大一點(diǎn)的咖啡屋(Coffee Shop)項目。屋子里有很多的桌子供客人坐,系統除了需要提供咖啡的"風(fēng)味"之外,還需要跟蹤咖啡被送到哪一個(gè)桌位上,因此,咖啡就有了桌子作為外蘊狀態(tài)。

由于外蘊狀態(tài)的存在,沒(méi)有外蘊狀態(tài)的單純享元模式不再符合要求。系統的設計可以利用有外蘊狀態(tài)的單純享元模式。系統的代碼如下:

 

using System;
using System.Collections;

public abstract class Order
{
  
// 將咖啡賣(mài)給客人
  public abstract void Serve(Table table);
  
// 返回咖啡的名字
  public abstract string GetFlavor();
}


public class Flavor : Order
{
  
private string flavor;

  
// 構造函數,內蘊狀態(tài)以參數方式傳入
  public Flavor(string flavor)
  
{
    
this.flavor = flavor;
  }


  
// 返回咖啡的名字
  public override string GetFlavor()
  
{
    
return this.flavor;
  }


  
// 將咖啡賣(mài)給客人
  public override void Serve(Table table)
  
{
    Console.WriteLine(
"Serving table {0} with flavor {1}", table.Number, flavor);
  }

}


public class FlavorFactory
{
  
private Hashtable flavors = new Hashtable();

  
public Order GetOrder(string key)
  
{
    
if(! flavors.ContainsKey(key))
      flavors.Add(key, 
new Flavor(key));

        
return ((Order)flavors[key]);
  }


  
public int GetTotalFlavorsMade()
  
{
    
return flavors.Count;
  }

}


public class Table
{
  
private int number;

  
public Table(int number)
  
{
    
this.number = number;
  }


  
public int Number
  
{
    
get return number; }
  }

}


public class Client
{
  
private static FlavorFactory flavorFactory;
  
private static int ordersMade = 0;

  
public static void Main( string[] args )
  
{
    flavorFactory 
= new FlavorFactory();

    TakeOrder(
"Black Coffee");
    TakeOrder(
"Capucino");
    TakeOrder(
"Espresso");
    TakeOrder(
"Capucino");
    TakeOrder(
"Espresso");
    TakeOrder(
"Black Coffee");
    TakeOrder(
"Espresso");
    TakeOrder(
"Espresso");
    TakeOrder(
"Black Coffee");
    TakeOrder(
"Capucino");
    TakeOrder(
"Capucino");
    TakeOrder(
"Black Coffee");

    Console.WriteLine(
"\nTotal Orders made: " + ordersMade);

    Console.WriteLine(
"\nTotal Flavor objects made: " + 
      flavorFactory.GetTotalFlavorsMade());
  }


  
private static void TakeOrder(string aFlavor)
  
{
    Order o 
= flavorFactory.GetOrder(aFlavor);
    
    
// 將咖啡賣(mài)給客人
    o.Serve(new Table(++ordersMade));
  }

}

 

 

七、 享元模式應當在什么情況下使用

當以下所有的條件都滿(mǎn)足時(shí),可以考慮使用享元模式:

  • 一個(gè)系統有大量的對象。
  • 這些對象耗費大量的內存。
  • 這些對象的狀態(tài)中的大部分都可以外部化。
  • 這些對象可以按照內蘊狀態(tài)分成很多的組,當把外蘊對象從對象中剔除時(shí),每一個(gè)組都可以?xún)H用一個(gè)對象代替。
  • 軟件系統不依賴(lài)于這些對象的身份,換言之,這些對象可以是不可分辨的。

滿(mǎn)足以上的這些條件的系統可以使用享元對象。

最后,使用享元模式需要維護一個(gè)記錄了系統已有的所有享元的表,而這需要耗費資源。因此,應當在有足夠多的享元實(shí)例可供共享時(shí)才值得使用享元模式。


八、 享元模式的優(yōu)點(diǎn)和缺點(diǎn)

享元模式的優(yōu)點(diǎn)在于它大幅度地降低內存中對象的數量。但是,它做到這一點(diǎn)所付出的代價(jià)也是很高的:

  • 享元模式使得系統更加復雜。為了使對象可以共享,需要將一些狀態(tài)外部化,這使得程序的邏輯復雜化。
  • 享元模式將享元對象的狀態(tài)外部化,而讀取外部狀態(tài)使得運行時(shí)間稍微變長(cháng)。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
用C++進(jìn)行 設計模式的解析和實(shí)現
享元模式一五子棋游戲
設計模式之享元模式,單例模式
設計模式學(xué)習筆記(十五)——結構型模式總結
享元模式(Flyweight)解析例子
享元模式——結構型模式(6)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久