IOS設計模式淺析之工廠方法模式(Factory Method)


概述

  在軟件系統中,經常面臨着“某個對象”的創建工作,由於需求的變化,這個對象的具體實現經常面臨着劇烈的變化,但是它卻擁有比較穩定的接口

  如何隔離出這個易變對象的變化,使得系統中“其它依賴該對象的對象”不隨着需求的改變而改變,這就是本章要說的Factory Method模式了。

定義

  “定義創建對象的接口,讓子類決定實例化哪一個類。工廠方法使得一個類的實例化延遲到其子類。”

  • 最初的定義出現於《設計模式》(Addison-Wesley,1994)

結構圖

 

  抽象產品Product(可以是接口或者抽象類)定義了工廠方法創建的對象的接口和產品的共性;ConcreteProduct實現了ProductCreator定義了返回Product類型對象的工廠方法;ConcreteCreator實現了Creator,返回具體的ConcreteProduct的實例。

  從結構圖可以看出,在工廠方法模式中,核心的工廠類(Creator)不再負責所有產品的創建,而是將具體創建工作交給子類(ConcreteCreator)去做。這個核心類僅僅負責給出具體工廠必須實現的接口,而不接觸哪一個產品類被實例化這種細節。與直接創建新的具體產品相比,工廠方法模式讓客戶程序可以要求由工廠方法創建的對象擁有一組共同的行為。這樣往類層次結構中引入新的具體產品時,並不需要修改客戶端代碼,因為返回的任何具體對象的接口都跟客戶端一直在用的從前的接口相同。從結構圖也可以看到,工廠方法模式中的工廠類與產品類往往具有平行的等級結構,它們之間一一對應。

示例

  根據工廠方法模式的定義和結構圖,現在將簡單工廠模式中的示例,用工廠方法模式來實現,先看使用工廠方法模式實現的結構圖:

  從圖中可以看到,在簡單工廠模式中,由工廠類(ChartFactory)根據參數負責創建具體的產品(線形圖、餅狀圖);而在工廠方法模式中,工廠類(Factory)只定義了一個創建產品的抽象接口,創建具體產品的工作由具體的工廠(線形圖工廠、餅狀圖工廠)來實現。如果需要增加其他類型的圖形繪制,那么使用簡單工廠模式實現的話,首先需要增加一個其他圖形繪制的類,例如柱狀圖(BarChart),然后修改工廠類(ChartFactory),在里面加分支語句來判斷;使用工廠方法模式實現的話,不僅需要增加圖形繪制類,還需要增加具體工廠類(BarFactory)。看到這里,可能大家會感覺到,工廠方法模式不但沒有減少難度,反而增加了一些類和復雜度。這樣來看,是不是沒有必要使用工廠方法模式?咱們再回顧一下開篇介紹的六大設計原則,有一個原則是“開放-關閉原則”,簡單工廠模式不僅對擴展開放,而且對修改也開放,違反了“開放-關閉原則”。工廠方法模式是簡單工廠模式的進一步抽象,它保持了簡單工廠模式的優點(去除了客戶端與具體產品的依賴),而且克服了它的缺點(違反開放-關閉原則)。它的缺點是每增加一個產品,就需要加一個產品工廠的類,增加了額外的開發工作量。理論分析就到這里,接下來看看代碼:

  IChart.h

1 @protocol IChart <NSObject>
2 
3 - (void)drawing;

  LineChart.m(部分代碼)

1 - (void)drawing
2 
3 {
4 
5     NSLog(@"LineChart drawing.");
6 
7 }

  PieChart.m(部分代碼)

1 - (void)drawing
2 
3 {
4 
5     NSLog(@"PieChart drawing.");
6 
7 }

  Factory.h

1 @protocol Factory <NSObject>
2 
3 - (id<IChart>)createChart;

  LineFactory.m(部分代碼)

1 - (id<IChart>)createChart
2 {
3 
4     return [[[LineChartalloc] init] autorelease];
5 
6 }

  PieFactory. .m(部分代碼)

1 - (id<IChart>)createChart
2 {
3 
4     return [[[PieChartalloc] init] autorelease];
5 
6 }

  客戶端調用代碼:

1         id<Factory> factory = [[[LineFactoryalloc] init] autorelease];
2 
3 //        id<Factory> factory = [[[PieFactory alloc] init] autorelease];
4 
5         id<IChart> chart = [factory createChart];
6 
7         [chart drawing];

  從調用代碼可以看出,工廠方法模式從代碼中消除了對應用程序特有類的耦合。代碼秩序處理Product抽象接口(這里是id<IChart>),這樣同一代碼就可以復用。

思考

  從上面的客戶端調用代碼看到,如果有多處調用繪圖的地方,我們需要每處都進行修改,這樣的話,實際上也沒有達到我們的效果:應對變化,盡可能少的修改代碼。那么該怎樣處理這種情況呢?

  下面一種方式可以做到:

1 //        id<Factory> factory = [[[LineFactory alloc] init] autorelease];
2 //        id<Factory> factory = [[[PieFactory alloc] init] autorelease];
3         id<Factory> factory = [[[NSClassFromString(@"PieFactory") alloc] init] autorelease];
4 
5         id<IChart> chart = [factory createChart];
6         [chart drawing];
7         
8         [NSNumber numberWithBool:YES];

  這樣的話,我們可以將@"PieFactory"放到配置文件中,當我們需要繪制線形圖的時候,只需要修改配置文件即可,客戶端的所有代碼都不需要改變。

何時使用工廠方法模式

  • 編譯時無法准確預期要創建的對象的類;
  • 類想讓其子類決定在運行時創建什么;
  • 類有若干輔助類為其子類,而你想將返回哪個子類這一信息局部化。

  源碼下載   返回目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM