工廠模式三部曲 - 工廠方法模式

該文章屬於<簡書 — 劉小壯>原創,轉載請註明:

<簡書 — 劉小壯> http://www.jianshu.com/p/03519d5e47b6git


緊接着上一篇文章開始寫,這是本系列中的第二篇文章了,這篇文章主要講一下工廠方法模式。在最後一篇__抽象工廠模式__的文章中,將會對這三篇文章進行一次總結。github

這篇文章中並無給出反射機制實現的代碼,主要是由於工廠方法模式就是爲了解決簡單工廠模式的一些缺點,然而使用了反射機制的簡單工廠模式已經不具有這些缺點,因此就不須要這篇文章中講的內容了。這篇文章主要仍是單一從設計模式的角度來說一下這個模式,帶你們認識一下這個設計模式。算法

本人理解可能不夠深入,這一系列文章中存在的問題,歡迎你們提出,謝謝!設計模式


博客配圖

什麼是工廠方法模式?

工廠方法模式和簡單工廠模式十分相似,大體結構是基本相似的。不一樣在於__工廠方法模式對工廠類進行了進一步的抽象__,將以前的一個工廠類抽象成了抽象工廠和工廠子類,抽象工廠定義一個建立抽象子類的接口,抽象工廠的子類實現這些接口並決定實例化哪一個抽象子類。工廠子類決定着建立哪一個抽象子類,外界決定着建立哪一種工廠子類,抽象子類和工廠子類是一一對應的學習

在工廠方法模式中,和簡單工廠模式同樣,對外隱藏了抽象子類的建立過程,外界只須要關心工廠類便可,負責實例化的工廠子類決定着最後的結果。atom

工廠方法模式主要包含四部分:
  • 工廠抽象類:定義建立抽象子類的接口,經過接口返回具體的抽象子類。
  • 工廠子類:繼承自工廠抽象類,並重寫父類的方法來建立對應的抽象子類。
  • 抽象類:定義抽象子類所需的屬性和方法,子類經過繼承自抽象類得到這些方法。
  • 抽象子類:繼承自抽象類,實現具體的操做。
爲何要用工廠方法模式?

在簡單工廠模式的代碼中,若是咱們沒有使用反射機制,只是標準的簡單工廠模式代碼。會有一個問題,就是若是新增長其餘運算功能,須要建立一個抽象子類,可是還須要修改工廠類中的代碼邏輯,這種設計是不符合__開放封閉原則__的。開放封閉原則對於修改是關閉的,對於擴展是開放的。並且將全部的操做子類的判斷和實例化都由一個工廠類完成,若是業務比較複雜會致使工廠類負擔較重。.net

工廠方法模式將以前負責生成具體抽象子類的工廠類,抽象爲工廠抽象類和工廠子類組成的一系列類。每建立一個抽象子類,就須要建立一個工廠子類,而且一一對應,由工廠子類去生成對應的抽象子類,由外界使用方來決定生成哪一個工廠子類。這樣在增長新的需求時,就不須要對工廠抽象類進行修改,而是對應新增的抽象子類建立對應的工廠子類便可。設計

業務場景

這裏的業務場景還用以前簡單工廠模式中提到的運算的例子,根據運算符的不一樣,計算兩個值的結果。code

UML類圖

工廠方法模式

這張類圖中增長了不少工廠子類,每個抽象子類都對應着一個工廠子類。這樣作的好處就是更佳靈活,每次新添加一個抽象子類,就生成一個工廠子類,對其餘類沒有任何影響。對象

簡單工廠模式違背了__開放封閉原則__,每次添加和刪除抽象子類的時候,都須要對工廠類進行操做,這樣不只對工廠類的擴展開放了,還開放了工廠類的修改,這就是違背開放封閉原則的。由於__按照開放封閉原則,新增長一個需求,應該是在原有類的基礎上進行擴展,而不是對原有類進行修改__。這樣整個模式在生成新算法類時,只是進行擴展而不對模式中原有的代碼進行修改,這就是符合開放封閉原則的。

代碼實現

工廠方法模式新建一個抽象子類時,選擇算法的操做仍是存在的,外界的靈活性依然存在,只是將原來由工廠類對抽象子類的建立,交給工廠子類去完成建立。以前增長和刪除修改的是工廠類,如今是增長工廠子類,這也是開放封閉原則的一個體現。以前的簡單工廠是在工廠類中建立抽象子類,工廠方法模式在工廠子類中建立抽象子類,依然封裝了對象實例化的過程。

因爲代碼比較多,因此這裏只貼出加法和減法運算的代碼,其餘運算代碼相似。

建立運算抽象類,聲明參與運算的兩個屬性和運算方法,下面的具體抽象子類繼承自這個類。
[@interface](https://my.oschina.net/u/996807) Operation : NSObject
[@property](https://my.oschina.net/property) (nonatomic, assign) CGFloat numberOne;
[@property](https://my.oschina.net/property) (nonatomic, assign) CGFloat numberTwo;
- (CGFloat)getResult;
[@end](https://my.oschina.net/u/567204)

@implementation Operation
- (CGFloat)getResult {
    return 0;
}
@end

@interface OperationAdd : Operation
@end

@implementation OperationAdd
- (CGFloat)getResult {
    return self.numberOne + self.numberTwo;
}
@end

@interface OperationSub : Operation
@end

@implementation OperationSub
- (CGFloat)getResult {
    return self.numberOne - self.numberTwo;
}
@end
抽象工廠類,定義了實例化實際運算類的方法,由子類繼承並實例化不一樣的運算類。
@interface Factory : NSObject
+ (Operation *)CreateOperation;
@end

@implementation Factory
+ (Operation *)CreateOperation {
    return nil;
}
@end

@interface FactoryAdd : Factory
@end

@implementation FactoryAdd
+ (Operation *)CreateOperation {
    return [OperationAdd new];
}
@end

@interface FactorySub : Factory
@end

@implementation FactorySub
+ (Operation *)CreateOperation {
    return [OperationSub new];
}
@end
外界使用時,直接實例化某個工廠子類便可,經過外界實例化某個工廠子類來選擇具體的運算類。
- (void)viewDidLoad {
    Operation *oper = [FactoryAdd CreateOperation];
    oper.numberOne = 13;
    oper.numberTwo = 24;
    NSLog(@"result : %f", [oper getResult]);
}

當需求發生改變時,須要進行算法的切換,外界只須要將工廠子類調用類方法的類名換一下便可,其餘地方都不用發生變化。這樣作就像一個「開關」同樣,在外界__由這個工廠子類的類型控制着抽象子類的實例化類型,而咱們並不知道抽象子類實例化的過程__。

工廠方法模式的優缺點

優勢

工廠方法模式的的優勢在於更大的靈活性,增長或刪除某種運算都不會對其餘地方形成影響,更佳符合開放封閉原則。

並且對抽象的使用更佳深刻,將工廠類也抽象爲了抽象工廠類和工廠子類,外界調用更加靈活,這也是對多態的一種體現。

缺點

工廠方法模式的缺點也是很是顯而易見的,工廠方法模式中新增一個抽象子類,意味着工廠子類要跟着成對增長,這樣會形成生成過多的類,工廠方法模式的複雜度也會隨之增長。

對於這個缺點,反射機制固然能夠很好的解決這個問題,工廠設計模式和反射機制的配合,可使這種設計模式更佳易用和靈活,減小了條件判斷和類的數量。

答疑解惑

使用工廠方法模式,看上去會感受到這不是更麻煩了嗎,直接在外界建立具體的抽象子類不行嗎?還用這麼麻煩的建立工廠子類,而後再用工廠子類去建立抽象子類。

我將從兩方面回答這個問題:
  1. 假設如今項目比較大,在外界不少地方都直接使用了抽象子類直接進行運算,這種方式在寫代碼的時候確實很快也很爽。可是,假設有一天,產品經理過來講要改需求,我如今不要加減乘除這四種運算了,我要換成更高級的其餘運算。。。若是這樣改起來改動就大了,須要把全部直接使用抽象子類實例化的地方都作修改。

  2. 這只是一種設計模式的思路,在程序的開發中__沒有一種設計模式是萬能的__,在適合的地方用適合的設計模式,或根據業務需求本身制定一套模式,這纔是最好的。只有最適合業務的模式,纔是最好的模式


前段時間寫了關於工廠模式的系列文章,這系列文章理解起來比較難懂。應廣大讀者的須要,這段時間專門給這系列文章補了Demo

Demo只是來輔助讀者更好的理解文章中的內容,應該博客結合Demo一塊兒學習,只看Demo仍是不能理解更深層的原理Demo中代碼都會有註釋,各位能夠打斷點跟着Demo執行流程走一遍,看看各個階段變量的值。

Demo地址劉小壯的Github

相關文章
相關標籤/搜索