C#設計模式(5)-Factory Method Pattern

 ------------http://www.cnblogs.com/zhenyulu/articles/36590.html

一、 工廠方法(Factory Method)模式

工廠方法(FactoryMethod)模式是類的創建模式,其用意是定義一個創建產品對象的工廠接口,將實際創建工作推遲到子類中。

工廠方法模式是簡單工廠模式的進一步抽象和推廣。由於使用了多態性,工廠方法模式保持了簡單工廠模式的優點,而且克服了它的缺點。

在工廠方法模式中,核心的工廠類不再負責所有產品的創建,而是將具體創建工作交給子類去做。這個核心類僅僅負責給出具體工廠必須實現的接口,而不接觸哪一個產品類被實例化這種細節。這使得工廠方法模式可以允許系統在不修改工廠角色的情況下引進新產品。

在Factory Method模式中,工廠類與產品類往往具有平行的等級結構,它們之間一一對應。


二、 Factory Method模式角色與結構:

 Pic41.gif

抽象工廠(Creator)角色:是工廠方法模式的核心,與應用程序無關。任何在模式中創建的對象的工廠類必須實現這個接口。

具體工廠(Concrete Creator)角色:這是實現抽象工廠接口的具體工廠類,包含與應用程序密切相關的邏輯,並且受到應用程序調用以創建產品對象。在上圖中有兩個這樣的角色:BulbCreator與TubeCreator。

抽象產品(Product)角色:工廠方法模式所創建的對象的超類型,也就是產品對象的共同父類或共同擁有的接口。在上圖中,這個角色是Light。

具體產品(Concrete Product)角色:這個角色實現了抽象產品角色所定義的接口。某具體產品有專門的具體工廠創建,它們之間往往一一對應。


三、 程序舉例:

None.gifusing System;
None.gif
None.gif
public abstract   class Light
ExpandedBlockStart.gif
{
InBlock.gif   
public abstract void TurnOn();
InBlock.gif   
public abstract void TurnOff();
ExpandedBlockEnd.gif}

None.gif
None.gif
public class BulbLight : Light
ExpandedBlockStart.gif
{
InBlock.gif   
public override void TurnOn()
ExpandedSubBlockStart.gif   
{ Console.WriteLine("Bulb Light is Turned on"); }
InBlock.gif
InBlock.gif   
public override void TurnOff()
ExpandedSubBlockStart.gif   
{ Console.WriteLine("Bulb Light is Turned off"); }
ExpandedBlockEnd.gif}

None.gif
None.gif
public class TubeLight : Light
ExpandedBlockStart.gif
{
InBlock.gif   
public override void TurnOn()
ExpandedSubBlockStart.gif   
{ Console.WriteLine("Tube Light is Turned on"); }
InBlock.gif
InBlock.gif   
public override void TurnOff()
ExpandedSubBlockStart.gif   
{ Console.WriteLine("Tube Light is Turned off"); }
ExpandedBlockEnd.gif}

None.gif
None.gif
public abstract   class Creator
ExpandedBlockStart.gif
{
InBlock.gif   
public abstract Light factory();
ExpandedBlockEnd.gif}

None.gif
None.gif
public class BulbCreator : Creator
ExpandedBlockStart.gif
{
InBlock.gif   
public override Light factory()
ExpandedSubBlockStart.gif   
return new BulbLight(); }
ExpandedBlockEnd.gif}

None.gif
None.gif
public class TubeCreator : Creator
ExpandedBlockStart.gif
{
InBlock.gif   
public override Light factory()
ExpandedSubBlockStart.gif   
return new TubeLight(); }
ExpandedBlockEnd.gif}

None.gif
None.gif
public class Client
ExpandedBlockStart.gif
{
InBlock.gif   
public static void Main()
ExpandedSubBlockStart.gif   
{
InBlock.gif      Creator c1 
= new BulbCreator();
InBlock.gif      Creator c2 
= new TubeCreator();
InBlock.gif
InBlock.gif      Light l1 
= c1.factory();
InBlock.gif      Light l2 
= c2.factory();
InBlock.gif
InBlock.gif      l1.TurnOn();
InBlock.gif      l1.TurnOff();
InBlock.gif
InBlock.gif      Console.WriteLine(
"-----------------");
InBlock.gif
InBlock.gif      l2.TurnOn();
InBlock.gif      l2.TurnOff();
ExpandedSubBlockEnd.gif   }

ExpandedBlockEnd.gif}

工廠方法的活動序列圖

 Pic42.gif

活動過程包括:

客戶端創建BulbCreator對象,客戶端持有此對象的類型是Creator,而實際類型是BulbCreator。然後客戶端調用BulbCreator的factory方法,之後BulbCreator調用BulbLight的構造函數創造出產品BulbLight對象。


四、 工廠方法模式與簡單工廠模式

工廠方法模式與簡單工廠模式再結構上的不同不是很明顯。工廠方法類的核心是一個抽象工廠類,而簡單工廠模式把核心放在一個具體類上。

工廠方法模式之所以有一個別名叫多態性工廠模式是因爲具體工廠類都有共同的接口,或者有共同的抽象父類。

當系統擴展需要添加新的產品對象時,僅僅需要添加一個具體對象以及一個具體工廠對象,原有工廠對象不需要進行任何修改,也不需要修改客戶端,很好的符合了"開放-封閉"原則。而簡單工廠模式在添加新產品對象後不得不修改工廠方法,擴展性不好。

工廠方法模式退化後可以演變成簡單工廠模式。


五、 Factory Method模式演化

使用接口或抽象類
抽象工廠角色和抽象場頻角色都可以選擇由接口或抽象類實現。

使用多個工廠方法
抽象工廠角色可以規定出多於一個的工廠方法,從而使具體工廠角色實現這些不同的工廠方法,這些方法可以提供不同的商業邏輯,以滿足提供不同的產品對象的任務。

產品的循環使用
工廠方法總是調用產品類的構造函數以創建一個新的產品實例,然後將這個實例提供給客戶端。而在實際情形中,工廠方法所做的事情可以相當複雜。

一個常見的複雜邏輯就是循環使用產品對象。工廠對象將已經創建過的產品登記到一個聚集中,然後根據客戶所請求的產品狀態,向聚集查詢。如果有滿足要求的產品對象,就直接將產品返回客戶端;如果聚集中沒有這樣的產品對象,那麼就創建一個新的滿足要求的產品對象,然後將這個對象登記到聚集中,再返還給客戶端。"享元模式(Flyweight Pattern)"就是這樣一個模式。

 Pic43.gif

多態性的喪失和模式的退化
一個工廠方法模式的實現依賴於工廠角色和產品角色的多態性。在有些情況下,這個模式可以出現退化。

工廠方法返回的類型應當是抽象類型,而不是具體類型。調用工廠方法的客戶端應當依賴抽象產品編程,而不是具體產品。如果工廠僅僅返回一個具體產品對象,便違背了工廠方法的用意,發生退化,這時就不再是工廠模式了。

工廠的等級結構:工廠對象應當有一個抽象的超類型。如果等級結構中只有一個具體工廠類的話,抽象工廠就可以省略,發生了退化。


六、 Factory Method模式與其它模式的關係

與工廠方法模式有關的模式還包括:
模板方法模式、MVC模式、享元模式、備忘錄模式


七、 另外一個例子

None.gif// Factory Method pattern -- Real World example  
None.gif

None.gif
using System;
None.gif
using System.Collections;
None.gif
None.gif
// "Product"
None.gif
abstract class Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteProduct"
None.gif
class SkillsPage : Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteProduct"
None.gif
class EducationPage : Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteProduct"
None.gif
class ExperiencePage : Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteProduct"
None.gif
class IntroductionPage : Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteProduct"
None.gif
class ResultsPage : Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteProduct"
None.gif
class ConclusionPage : Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteProduct"
None.gif
class SummaryPage : Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteProduct"
None.gif
class BibliographyPage : Page
ExpandedBlockStart.gif
{
ExpandedBlockEnd.gif}

None.gif
None.gif
// "Creator"
None.gif
abstract class Document
ExpandedBlockStart.gif
{
InBlock.gif  
// Fields
InBlock.gif
   protected ArrayList pages = new ArrayList();
InBlock.gif
InBlock.gif  
// Constructor
InBlock.gif
   public Document()
ExpandedSubBlockStart.gif  
{
InBlock.gif    
this.CreatePages();
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
// Properties
InBlock.gif
   public ArrayList Pages
ExpandedSubBlockStart.gif  
{
ExpandedSubBlockStart.gif    
getreturn pages; }
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
// Factory Method
InBlock.gif
   abstract public void CreatePages();
ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteCreator"
None.gif
class Resume : Document
ExpandedBlockStart.gif
{
InBlock.gif  
// Factory Method implementation
InBlock.gif
   override public void CreatePages()
ExpandedSubBlockStart.gif  
{
InBlock.gif    pages.Add( 
new SkillsPage() );
InBlock.gif    pages.Add( 
new EducationPage() );
InBlock.gif    pages.Add( 
new ExperiencePage() );
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
// "ConcreteCreator"
None.gif
class Report : Document
ExpandedBlockStart.gif
{
InBlock.gif  
// Factory Method implementation
InBlock.gif
   override public void CreatePages()
ExpandedSubBlockStart.gif  
{
InBlock.gif    pages.Add( 
new IntroductionPage() );
InBlock.gif    pages.Add( 
new ResultsPage() );
InBlock.gif    pages.Add( 
new ConclusionPage() );
InBlock.gif    pages.Add( 
new SummaryPage() );
InBlock.gif    pages.Add( 
new BibliographyPage() );
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gif
/// <summary>
InBlock.gif
///  FactoryMethodApp test
ExpandedBlockEnd.gif
/// </summary>

None.gifclass FactoryMethodApp
ExpandedBlockStart.gif
{
InBlock.gif  
public static void Main( string[] args )
ExpandedSubBlockStart.gif  
{
InBlock.gif    Document[] docs 
= new Document[ 2 ];
InBlock.gif
InBlock.gif    
// Note: constructors call Factory Method
InBlock.gif
    docs[0= new Resume();
InBlock.gif    docs[
1= new Report();
InBlock.gif
InBlock.gif    
// Display document pages
InBlock.gif
     foreach( Document document in docs )
ExpandedSubBlockStart.gif    
{
InBlock.gif      Console.WriteLine( 
" " + document + " ------- " );
InBlock.gif      
foreach( Page page in document.Pages )
InBlock.gif        Console.WriteLine( 
" " + page );
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}


參考文獻:
閻宏,《Java與模式》,電子工業出版社
[美]James W. Cooper,《C#設計模式》,電子工業出版社
[美]Alan Shalloway  James R. Trott,《Design Patterns Explained》,中國電力出版社
[美]Robert C. Martin,《敏捷軟件開發-原則、模式與實踐》,清華大學出版社
[美]Don Box, Chris Sells,《.NET本質論 第1卷:公共語言運行庫》,中國電力出版社

發佈了72 篇原創文章 · 獲贊 2 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章