那些你必須知道的設(shè)計(jì)模式之簡單工廠模式温数,工廠模式,抽象工廠模式

哲學(xué)上說“是什么,為什么,怎么用”是認(rèn)識(shí)問題的邏輯思維過程.

本文將以廠長工廠造車為例子講述這三種設(shè)計(jì)模式蜻势。


簡單工廠模式

是什么

簡單工廠模式是屬于創(chuàng)建型模式撑刺,又叫做靜態(tài)工廠方法(Static Factory Method)模式,但不屬于23種GOF設(shè)計(jì)模式之一握玛。簡單工廠模式是由一個(gè)工廠對(duì)象決定創(chuàng)建出哪一種產(chǎn)品類的實(shí)例够傍。

簡單工廠模式

簡單工廠模式主要包含三部分:
工廠類角色:本模式核心,含有商業(yè)邏輯和判斷邏輯挠铲,根據(jù)邏輯不同冕屯,生產(chǎn)具體的工廠產(chǎn)品。
抽象產(chǎn)品角色:定義了工廠方法創(chuàng)建的對(duì)象的接口拂苹。由接口或者抽象類來實(shí)現(xiàn)安聘。
具體產(chǎn)品角色:工廠類所創(chuàng)建的對(duì)象就是此實(shí)例。由具體類實(shí)現(xiàn)瓢棒。

怎么用

第一年:生意來了浴韭,老板就一個(gè)廠要造benz,audi的脯宿。

#import "CarSampleFactory.h"

@implementation CarSampleFactory
//    抽象產(chǎn)品就是具體產(chǎn)品的接口囱桨,直接用一句話代替了
-(void)createCarWithName:(NSString *)name {
    NSArray *car = @[@"Benz", @"BMW", @"Audi"];
    NSUInteger index  = [car indexOfObject:name];
    
    switch (index) {
        case 0:
            NSLog(@"生產(chǎn)了Benz具體產(chǎn)品(alloc你需要的類)");
            break;
        case 1:
            NSLog(@"生產(chǎn)了Audi具體產(chǎn)品");
            break;
        default:
            break;
    }
}
@end

為什么

  • 優(yōu)點(diǎn)
    工廠類是整個(gè)模式的關(guān)鍵.包含了必要的邏輯判斷,根據(jù)外界給定的信息,決定究竟應(yīng)該創(chuàng)建哪個(gè)具體類的對(duì)象.通過使用工廠類,僅僅需要負(fù)責(zé)“消費(fèi)”對(duì)象就可以了。而不必管這些對(duì)象究竟如何創(chuàng)建的嗅绰。所以也稱之‘上帝類’舍肠。
  • 缺點(diǎn)
    由于工廠類集中了所有實(shí)例的創(chuàng)建邏輯,違反了高內(nèi)聚責(zé)任分配原則窘面,將全部創(chuàng)建邏輯集中到了一個(gè)工廠類中翠语。每增加一種品牌的車子,都要修改邏輯判斷處代碼财边。不符合開閉原則,肌括。

這些缺點(diǎn)在工廠方法模式中得到了一定的克服。


工廠模式

是什么

工廠方法模式是一種常用的對(duì)象創(chuàng)建型設(shè)計(jì)模式,此模式的核心精神是封裝類中不變的部分,提取其中個(gè)性化善變的部分為獨(dú)立類谍夭,通過依賴注入以達(dá)到解耦黑滴、復(fù)用和方便后期維護(hù)拓展的目的。

簡單工廠模式
  • 抽象工廠(Creator)角色:是工廠方法模式的核心紧索,與應(yīng)用程序無關(guān)袁辈。任何在模式中創(chuàng)建的對(duì)象的工廠類必須實(shí)現(xiàn)這個(gè)接口或者繼承
  • 具體工廠(Concrete Creator)角色:這是實(shí)現(xiàn)抽象工廠接口的具體工廠類珠漂,包含與應(yīng)用程序密切相關(guān)的邏輯晚缩,并且受到應(yīng)用程序調(diào)用以創(chuàng)建產(chǎn)品對(duì)象。
  • 抽象產(chǎn)品(Product)角色:工廠方法模式所創(chuàng)建的對(duì)象的超類型媳危,也就是產(chǎn)品對(duì)象的共同父類或共同擁有的接口荞彼。
  • 具體產(chǎn)品(Concrete Product)角色:這個(gè)角色實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口。某具體產(chǎn)品有專門的具體工廠創(chuàng)建待笑,它們之間往往一一對(duì)應(yīng)鸣皂。(benz車)

怎么用

第二年:生意越做越大,Audi啊來了暮蹂,廠子忙不過了寞缝。聰明的廠長又開了三個(gè)廠子,并且叫了一個(gè)管理者(抽象工廠)來管理這些工廠椎侠。

#import "ViewController.h"

//    工廠方法
//  第一種情況是對(duì)于某個(gè)產(chǎn)品第租,調(diào)用者清楚地知道應(yīng)該使用哪個(gè)具體工廠服務(wù),實(shí)例化該具體工廠我纪,生產(chǎn)出具體的產(chǎn)品來慎宾。

    BMWFactory *BMWF = [[BMWFactory alloc] init];
    [BMWF CreateCarBMW];
    
//  第二種情況,只是需要一種產(chǎn)品浅悉,而不想知道也不需要知道究竟是哪個(gè)工廠為生產(chǎn)的趟据,即最終選用哪個(gè)具體工廠的決定權(quán)在生產(chǎn)者一方,它們根據(jù)當(dāng)前系統(tǒng)的情況來實(shí)例化一個(gè)具體的工廠返回給使用者术健,而這個(gè)決策過程這對(duì)于使用者來說是透明的(類似多態(tài))
    CarAbstractFactory *caf = [[BMWFactory alloc] init];
    [caf CreateCarFactoy];
    
    caf = [[BenzFactory alloc] init];
    [caf CreateCarFactoy];
#import "CarAbstractFactory.h"

@implementation CarAbstractFactory
//抽象工廠
-(void)CreateCarFactoye{
    
}
@end

#import "BenzFactory.h"
//具體工廠
@implementation BenzFactory
-(void)CreateCarFactoy{
    [self CreateCarBenz];
}

- (void)CreateCarBenz{
//具體產(chǎn)品
    NSLog(@"工廠方法生產(chǎn)了Benz具體產(chǎn)品(alloc你需要的類)");
}
@end
#import "BMWFactory.h"

@implementation BMWFactory
-(void)CreateCarFactoy{
    [self CreateCarBMW];
    
}
- (void)CreateCarBMW{
    NSLog(@"工廠方法生產(chǎn)了BMW具體產(chǎn)品(alloc你需要的類)");
}
@end
#import "AudiFactory.h"

@implementation AudiFactory
-(void)CreateCarFactoy{
    [self CreateCarAudi];
}
- (void)CreateCarAudi{
    NSLog(@"工廠方法生產(chǎn)了Benz具體產(chǎn)品(alloc你需要的類)");
}
@end

為什么

  • 優(yōu)點(diǎn)
    工廠方法模式是簡單工廠模式的衍生汹碱,相當(dāng)于橫向擴(kuò)展。當(dāng)有新的產(chǎn)品(法拉利汽車)荞估,只要新建繼承抽象工廠的類就好了咳促。完全符合繼承原則。

  • 缺點(diǎn)
    但是產(chǎn)品種類特別多的時(shí)候勘伺,就會(huì)產(chǎn)生大量的工廠類跪腹。所以對(duì)于類似的產(chǎn)品我們還是用簡單工廠來實(shí)現(xiàn)。復(fù)雜的業(yè)務(wù)邏輯可以使用兩者結(jié)合的模式飞醉。開發(fā)者依照自身取舍冲茸。

可是benz和audi等工廠突然又想生產(chǎn)自己suv,跑車等等,那只能在工廠里寫個(gè)各種邏輯判斷,好吧轴术,又違反了開閉原則难衰,又回到類似簡單工廠的弊端。這時(shí)候就需要用到抽象工廠模式逗栽。


抽象工廠模式

是什么

是工廠方法設(shè)計(jì)模式的一種擴(kuò)展盖袭。當(dāng)有多個(gè)抽象角色時(shí),使用的一種工廠模式祭陷。


抽象工廠
  • AbstractFactory(抽象工廠):它聲明了一組用于創(chuàng)建一族產(chǎn)品的方法苍凛,每一個(gè)方法對(duì)應(yīng)一種產(chǎn)品趣席。
  • ConcreteFactory(具體工廠):它實(shí)現(xiàn)了在抽象工廠中聲明的創(chuàng)建產(chǎn)品的方法兵志,生成一組具體產(chǎn)品,這些產(chǎn)品構(gòu)成了一個(gè)產(chǎn)品族宣肚,每一個(gè)產(chǎn)品都位于某個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)中想罕。
  • AbstractProduct(抽象產(chǎn)品):它為每種產(chǎn)品聲明接口,在抽象產(chǎn)品中聲明了產(chǎn)品所具有的業(yè)務(wù)方法霉涨。
  • ConcreteProduct(具體產(chǎn)品):它定義具體工廠生產(chǎn)的具體產(chǎn)品對(duì)象按价,實(shí)現(xiàn)抽象產(chǎn)品接口中聲明的業(yè)務(wù)方法。
產(chǎn)品族和等級(jí)結(jié)構(gòu)示意圖
  1. 產(chǎn)品等級(jí)結(jié)構(gòu):產(chǎn)品等級(jí)結(jié)構(gòu)即產(chǎn)品的繼承結(jié)構(gòu)(三種品牌汽車構(gòu)成了三個(gè)不同的產(chǎn)品等級(jí)結(jié)構(gòu))
  2. 產(chǎn)品族:在抽象工廠模式中笙瑟,產(chǎn)品族是指由同一個(gè)工廠生產(chǎn)的楼镐,位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中的一組產(chǎn)品。比如(suv工廠里生產(chǎn)的三個(gè)品牌車型)

怎么用

第三年:audi往枷,benz框产,bmw告訴廠長,我們這次的訂單需要分成suv错洁,business秉宿,sport三種類型的車。這時(shí)候管理蠻不過來了屯碴。所以廠子又請(qǐng)了兩個(gè)管理描睦。分別管理三個(gè)品牌的車子。

//  抽象工廠兩種情況同工廠方法上
//  method 1
    SUVFactory *suvf = [[SUVFactory alloc] init];
    [suvf createAudiCar];
    
//  method 2
    AbstractFactorys *af = [[SportsFactorys alloc] init];
    [af CreateAudiFactoy];
#import <Foundation/Foundation.h>

@interface AbstractFactorys : NSObject
//抽象工廠(三個(gè)管理者)
-(void)CreateBenzFactoy;
-(void)CreateBMWFactoy;
-(void)CreateAudiFactoy;
@end
#import "SUVFactory.h"
//具體工廠
@implementation SUVFactory
-(void)createBenzCar{
    NSLog(@"抽象工廠方法生產(chǎn)了benzSUV");
}
-(void)createBWMCar{
    NSLog(@"抽象工廠方法生產(chǎn)了BWMSUV");
}
-(void)createAudiCar{
    NSLog(@"抽象工廠方法生產(chǎn)了AudiSUV");
}
@end

為什么

抽象工廠模式與工廠方法模式最大的區(qū)別在于导而,工廠方法模式針對(duì)的是一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)忱叭,而抽象工廠模式需要面對(duì)多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu),一個(gè)工廠等級(jí)結(jié)構(gòu)可以負(fù)責(zé)多個(gè)不同產(chǎn)品等級(jí)結(jié)構(gòu)中的產(chǎn)品對(duì)象的創(chuàng)建今艺。當(dāng)一個(gè)工廠等級(jí)結(jié)構(gòu)可以創(chuàng)建出分屬于不同產(chǎn)品等級(jí)結(jié)構(gòu)的一個(gè)產(chǎn)品族中的所有對(duì)象時(shí)韵丑,抽象工廠模式比工廠方法模式更為簡單、更有效率洼滚,如使用工廠方法模式蒜埋,上圖所示結(jié)構(gòu)需要提供15個(gè)具體工廠该贾,而使用抽象工廠模式只需要提供3個(gè)具體工廠坑赡。

當(dāng)增加新的產(chǎn)品族的時(shí)候跑芳,符合“開閉原則”,只需讓產(chǎn)品繼承相應(yīng)的抽象產(chǎn)品猜欺,對(duì)象的工廠繼承抽象工廠即可,而無需修改其他的代碼。

當(dāng)增加產(chǎn)品等級(jí)結(jié)構(gòu)的時(shí)候值桩,不符合“開閉原則”,如新添加大眾豪椿,那么在soprt奔坟,suv,business三個(gè)具體工廠里面都進(jìn)行修改搭盾。當(dāng)然我們可以配合反射機(jī)制來對(duì)抽象工廠進(jìn)行優(yōu)化咳秉。

//根據(jù)字符串來創(chuàng)建類
    NSClassFromString(<#NSString * _Nonnull aClassName#>)```
----

###總結(jié)

簡單工廠啟示是工廠方法的一種極端實(shí)現(xiàn),工廠方法是抽象方法的一種極端實(shí)現(xiàn)鸯隅。在實(shí)際項(xiàng)目中澜建,如果不是項(xiàng)目過大或者功能過于復(fù)雜,抽象工廠設(shè)計(jì)模式一般使用不到蝌以。簡單工廠模式反而是用的比較頻繁炕舵。但是這種思想我們還是需要借鑒的。在CoCoa Touch框架中的'類簇'便是基于抽象工廠模式設(shè)計(jì)跟畅。NSNumber就是最好的例子咽筋。
NSNumber *boolNumber = [NSNumber numberWithBool:YES];
NSLog(@"%@",[[boolNumber class] description]);

// 輸出 __NSCFBoolean
NSLog(@"%d",[boolNumber boolValue]);
//輸出1
NSNumber(抽象工廠)->NSCFBoolean(具體工廠子類)-> 重載boolValue工廠方法 ->返回實(shí)際產(chǎn)品

這種設(shè)計(jì)多類型的對(duì)象的創(chuàng)建。好的模式應(yīng)該是變成一種抽象徊件,不暴露創(chuàng)建過程中任何不必要的細(xì)節(jié)和創(chuàng)建對(duì)象的具體類型奸攻。



ps:最后廠長去打lol了

都看到最后了還不給個(gè)喜歡么……

[demo](https://github.com/Xmanzn/Design-Patterns)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市庇忌,隨后出現(xiàn)的幾起案子舞箍,更是在濱河造成了極大的恐慌,老刑警劉巖皆疹,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疏橄,死亡現(xiàn)場離奇詭異,居然都是意外死亡略就,警方通過查閱死者的電腦和手機(jī)捎迫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來表牢,“玉大人窄绒,你說我怎么就攤上這事〈扌耍” “怎么了彰导?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵蛔翅,是天一觀的道長。 經(jīng)常有香客問我位谋,道長山析,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任掏父,我火速辦了婚禮笋轨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赊淑。我一直安慰自己爵政,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布陶缺。 她就那樣靜靜地躺著钾挟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪组哩。 梳的紋絲不亂的頭發(fā)上等龙,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天处渣,我揣著相機(jī)與錄音伶贰,去河邊找鬼。 笑死罐栈,一個(gè)胖子當(dāng)著我的面吹牛黍衙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播荠诬,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼琅翻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了柑贞?” 一聲冷哼從身側(cè)響起方椎,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钧嘶,沒想到半個(gè)月后棠众,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡有决,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年闸拿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片书幕。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡新荤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出台汇,到底是詐尸還是另有隱情苛骨,我是刑警寧澤篱瞎,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站痒芝,受9級(jí)特大地震影響奔缠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吼野,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一校哎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瞳步,春花似錦闷哆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嘀倒,卻和暖如春屈留,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背测蘑。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工灌危, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碳胳。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓勇蝙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挨约。 傳聞我的和親對(duì)象是個(gè)殘疾皇子味混,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容