工廠模式概述
工廠模式是設(shè)計(jì)模式的一種悔醋,從功能上來(lái)說(shuō)绸狐,它的主要作用是創(chuàng)建對(duì)象。細(xì)分一下鳞滨,有三種不同類(lèi)型的工廠模式洞焙,即,
- 簡(jiǎn)單工廠模式
- 工廠模式
- 抽象工廠模式
本文使用swift編碼拯啦,試圖通過(guò)簡(jiǎn)單的代碼和配圖簡(jiǎn)要說(shuō)明工廠模式的使用澡匪。既然是關(guān)于工廠模式爽室,那么直接映射到現(xiàn)實(shí)世界凌那,就用汽車(chē)工廠生產(chǎn)汽車(chē)這樣一個(gè)模型來(lái)描述工廠模式的使用和逐步改進(jìn)的過(guò)程。
創(chuàng)建對(duì)象存在的問(wèn)題
這里假設(shè)镜豹,工廠可以生產(chǎn)汽車(chē)(Car)甫匹,這個(gè)數(shù)據(jù)模型可以用swift像下面這樣定義甸鸟,
protocol VehicleFeature {
func speedUp() -> Void
func numberOfWheelNumber() -> Int
}
class Vehicle: VehicleFeature {
private var name: String? = "Vehicle"
private var wheelNumber: Int?
func speedUp() {
print("car speed up")
}
func numberOfWheelNumber() -> Int {
if let wheelNumber = self.wheelNumber {
return wheelNumber
}
return 0
}
}
class Car: Vehicle {
override func speedUp() {
print("car speed up")
}
override func numberOfWheelNumber() -> Int {
if let wheelNumber = self.wheelNumber {
return wheelNumber
}
return 0
}
}
上面代碼定義了VehicleFeature協(xié)議,該協(xié)議中定義了-speedUp和-numberOfWheelNumber兩個(gè)方法兵迅,父類(lèi)Vehicle定義了name和wheelNumber兩個(gè)可選值屬性哀墓,并且Vehicle實(shí)現(xiàn)了VehicleFeature協(xié)議,子類(lèi)Car繼承父類(lèi)Vehicle喷兼。
這時(shí)客戶(hù)想要一輛汽車(chē)Car篮绰,直接調(diào)用Car的初始化方法let car = Car()
,即可創(chuàng)建一個(gè)Car對(duì)象季惯。
想一想吠各,隨著工廠業(yè)務(wù)的擴(kuò)張,這時(shí)候還需要生產(chǎn)摩托車(chē)(MotorBicycle)和大巴車(chē)(Bus)勉抓,我們得新增加MotorBicycle和Bus兩個(gè)類(lèi)贾漏,如下代碼所示,
class MotorBicycle: Vehicle {
override func speedUp() {
print("motorBicycle speed up")
}
override func numberOfWheelNumber() -> Int {
if let wheelNumber = self.wheelNumber {
return wheelNumber
}
return 0
}
}
class Bus: Vehicle {
override func speedUp() {
print("bus speed up")
}
override func numberOfWheelNumber() -> Int {
if let wheelNumber = self.wheelNumber {
return wheelNumber
}
return 0
}
}
通過(guò)let motorBicycle = MotorBicycle(); let bus = Bus()
即可為客戶(hù)創(chuàng)建MotorBicycle和Bus對(duì)象藕筋。
在開(kāi)發(fā)過(guò)程中纵散,通過(guò)上述方式創(chuàng)建對(duì)象是一種很常見(jiàn)的方法,不過(guò)我們應(yīng)該意識(shí)到,隨著業(yè)務(wù)的調(diào)整和擴(kuò)展伍掀,類(lèi)似let car = Car()
這樣的對(duì)象初始化方法會(huì)散落在項(xiàng)目的各個(gè)角落掰茶,代碼維護(hù)的成本越來(lái)越高,比如現(xiàn)在給父類(lèi)Vehicle添加一個(gè)-required init方法蜜笤,用以在初始化時(shí)候指定車(chē)輛(Vehicle)車(chē)輪數(shù)量濒蒋,代碼如下,
class Vehicle: VehicleFeature {
private var name: String? = "Vehicle"
private var wheelNumber: Int?
required init(wheelNumber: Int) {
self.wheelNumber = wheelNumber
}
func speedUp() {
print("car speed up")
}
func numberOfWheelNumber() -> Int {
if let wheelNumber = self.wheelNumber {
return wheelNumber
}
return 0
}
}
在swift中把兔,如果父類(lèi)定義了-required init方法沪伙,那么子類(lèi)定義-init方法時(shí)必須要定義同樣的-required init方法,所以上述的Car县好、MotorBicycle和Bus三個(gè)子類(lèi)围橡,也要添加跟父類(lèi)Vehicle同樣的-required init方法,代碼如下缕贡,
class Car: Vehicle {
required init(wheelNumber: Int) {
super.init(wheelNumber: wheelNumber)
}
override func speedUp() {
print("car speed up")
}
override func numberOfWheelNumber() -> Int {
if let wheelNumber = self.wheelNumber {
return wheelNumber
}
return 0
}
}
class MotorBicycle: Vehicle {
required init(wheelNumber: Int) {
super.init(wheelNumber: wheelNumber)
}
override func speedUp() {
print("motorBicycle speed up")
}
override func numberOfWheelNumber() -> Int {
if let wheelNumber = self.wheelNumber {
return wheelNumber
}
return 0
}
}
class Bus: Vehicle {
required init(wheelNumber: Int) {
super.init(wheelNumber: wheelNumber)
}
override func speedUp() {
print("bus speed up")
}
override func numberOfWheelNumber() -> Int {
if let wheelNumber = self.wheelNumber {
return wheelNumber
}
return 0
}
}
經(jīng)過(guò)上面的更改某饰,我們需要通過(guò)帶參數(shù)的初始話方法let car = Car(wheelNumber: 4)
和let motorBicycle = MotorBicycle(wheelNumber: 2)
來(lái)創(chuàng)建對(duì)象,項(xiàng)目中大量的創(chuàng)建對(duì)象的代碼得重新編碼和調(diào)整善绎。
簡(jiǎn)單工廠模式
上面的demo黔漂,簡(jiǎn)單說(shuō)明了創(chuàng)建對(duì)象時(shí)候可能存在的問(wèn)題,遇到這樣的問(wèn)題禀酱,我們?cè)撛趺磧?yōu)化呢炬守?
這時(shí)候簡(jiǎn)單工廠模式(Simple Factory Pattern)出現(xiàn)了,它可以短期內(nèi)緩解我們的壓力〖粮現(xiàn)在客戶(hù)需要一輛車(chē)Car减途,我們不再通過(guò)let car = ...
來(lái)創(chuàng)建對(duì)象,而是將創(chuàng)建對(duì)象的任務(wù)交給簡(jiǎn)單工廠曹洽,這時(shí)需要在該模型中增加一個(gè)新的角色簡(jiǎn)單工廠(SimpleFactory)鳍置,它的主要功能是根據(jù)客戶(hù)輸入的機(jī)車(chē)類(lèi)型,為用戶(hù)創(chuàng)建對(duì)應(yīng)的機(jī)車(chē)送淆,下面的代碼展示了簡(jiǎn)單工廠模式的使用税产,
enum FactoryVehicleType {
case CarType
case MotorBicycle
case BusType
}
class SimpleFactory {
func createVehicle(vehicleType: FactoryVehicleType) -> Vehicle {
switch vehicleType {
case .CarType:
return Car(wheelNumber: 4)
case .MotorBicycle:
return MotorBicycle(wheelNumber: 2)
case .BusType:
return Bus(wheelNumber: 4)
}
}
}
上述代碼,定義了枚舉類(lèi)型FactoryVehicleType偷崩,它描述了簡(jiǎn)單工廠可以創(chuàng)建的幾種車(chē)型辟拷,新增加的SimpleFactory(簡(jiǎn)單工廠類(lèi)),它包含-createVehicle方法阐斜,該方法根據(jù)輸入的FactoryVehicle枚舉值類(lèi)型衫冻,創(chuàng)建對(duì)應(yīng)的車(chē)型。
上述代碼存在了這樣幾個(gè)角色:抽象產(chǎn)品(Abstract Product)谒出、具體產(chǎn)品(Concrete Product)隅俘、簡(jiǎn)單工廠(SimpleFactory)以及客戶(hù)類(lèi)(Consumer)邻奠,其中SimpleFactory是簡(jiǎn)單工廠模式的核心類(lèi),它們之間的關(guān)系如下UML圖所示为居,
通過(guò)使用簡(jiǎn)單工廠方法碌宴,為我們創(chuàng)建對(duì)象提供了方便,也節(jié)省了開(kāi)發(fā)者的精力颜骤。假設(shè)現(xiàn)在改動(dòng)了父類(lèi)Vehicle的required init方法唧喉,各個(gè)子類(lèi)也要做相應(yīng)的改動(dòng)捣卤,此時(shí)我們只需在SimpleFactory的-createVehicle方法中改動(dòng)創(chuàng)建子類(lèi)的初始化方法即可忍抽,而項(xiàng)目各個(gè)角落中通過(guò)SimpleFactory創(chuàng)建子類(lèi)對(duì)象的零散的代碼都不需要做任何的改動(dòng),這無(wú)疑是一個(gè)大大的改進(jìn)董朝。
但是簡(jiǎn)單工廠模式也存在很大的不足鸠项,那就是隨著工廠規(guī)模的增加和客戶(hù)的需求,現(xiàn)在需要生產(chǎn)更多類(lèi)型的車(chē)輛子姜,比如現(xiàn)在要增加生產(chǎn)坦克(Tank)和SUV祟绊,這時(shí)候我們得重新調(diào)整SimpleFactory,代碼如下哥捕,
enum FactoryVehicleType {
case CarType
case MotorBicycle
case BusType
case TankType
case SUVType
}
class SimpleFactory {
func createVehicle(vehicleType: FactoryVehicleType) -> Vehicle {
switch vehicleType {
case .CarType:
return Car(wheelNumber: 4)
case .MotorBicycle:
return MotorBicycle(wheelNumber: 2)
case .BusType:
return Bus(wheelNumber: 4)
case .TankType:
return Tank(wheelNumber: 16)
case .SUVType:
return SUV(wheelNumber: 4)
}
}
}
可以想象牧抽,隨著工廠的發(fā)展,SimpleFactory的代碼會(huì)越來(lái)越臃腫遥赚,每增加一條新型車(chē)輛的生產(chǎn)線扬舒,就得新增加FactoryVehicleType枚舉類(lèi)型的種類(lèi),同時(shí)更改SimpleFactory的-createVehicle方法凫佛。所以說(shuō)讲坎,SimpleFactory只能短期內(nèi)緩解工廠的壓力,這種方案并不是一個(gè)長(zhǎng)久之計(jì)愧薛。
這么說(shuō)來(lái)晨炕,SimpleFactory并不是像它的名字一樣看起來(lái)簡(jiǎn)單和簡(jiǎn)潔,這里的Simple
也許僅僅代表了簡(jiǎn)單工廠模式適合處理相對(duì)簡(jiǎn)單的業(yè)務(wù)場(chǎng)景毫炉。粗略地看一下臃腫不堪的SimpleFactory代碼瓮栗,我們可以說(shuō)SimpleFactory之所以臃腫不堪,是因?yàn)樗袚?dān)的職能太多了瞄勾,它要負(fù)責(zé)創(chuàng)建Car遵馆、Bus和MotorBicycle,還要負(fù)責(zé)創(chuàng)建Tank和SUV丰榴,在將來(lái)它可能還要承擔(dān)更多更繁雜的職能货邓,這顯然違背了軟件開(kāi)發(fā)中的“單一職責(zé)”和“開(kāi)閉原則”。
開(kāi)閉原則:Open-Closed Principle,OCP) "Software entities should be open for extension,but closed for modification"四濒。翻譯一下:“軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開(kāi)放换况,對(duì)修改關(guān)閉”职辨。通俗點(diǎn)來(lái)說(shuō)就是:軟件系統(tǒng)中包含的各種組件,例如模塊(Modules)戈二、類(lèi)(Classes)以及功能(Functions)等等舒裤,應(yīng)該在不修改現(xiàn)有代碼的基礎(chǔ)上,引入新功能觉吭。開(kāi)閉原則中“開(kāi)”腾供,是指對(duì)于組件功能的擴(kuò)展是開(kāi)放的,是允許對(duì)其進(jìn)行功能擴(kuò)展的鲜滩;開(kāi)閉原則中“閉”伴鳖,是指對(duì)于原有代碼的修改是封閉的,即不應(yīng)該修改原有的代碼徙硅。
怎樣優(yōu)化SimpleFactroy榜聂,其中的關(guān)鍵點(diǎn)和問(wèn)題所在其實(shí)就是SimpleFactory職責(zé)太多、代碼臃腫嗓蘑,這時(shí)我們需要對(duì)SimpleFactory的職能進(jìn)行拆分须肆,將它創(chuàng)建車(chē)輛的各條業(yè)務(wù)線拆分給不同的工廠,這催生了FactoryPattern(工廠模式)桩皿。
工廠模式
FactoryPattern的出現(xiàn)就是為了簡(jiǎn)化SimpleFactory豌汇,它也符合軟件開(kāi)發(fā)和設(shè)計(jì)中的單一職責(zé)原則。就像現(xiàn)實(shí)世界中一樣泄隔,現(xiàn)在已經(jīng)不可能存在這樣一個(gè)巨型的工廠拒贱,它需要負(fù)責(zé)生產(chǎn)各種類(lèi)型的汽車(chē),我們需要的是具有單一職能并且高度專(zhuān)業(yè)化的工廠梅尤,這種單一職責(zé)的工廠也是從SimpleFactory拆分而來(lái)柜思,那么對(duì)應(yīng)于上面的代碼demo,我們拆分SimpleFactory巷燥,對(duì)于已經(jīng)定義的Car赡盘、Bus、MotorBicycle等數(shù)據(jù)模型則不需要改變缰揪,我們只需要增加對(duì)應(yīng)的三個(gè)工廠類(lèi)和一個(gè)抽象工廠協(xié)議(AbstractFactory)陨享,如下代碼所示,
protocol AbstractFactory {
func createVehicle() -> Vehicle
}
class CarFactory: AbstractFactory {
func createVehicle() -> Vehicle {
return Car(wheelNumber: 4)
}
}
class BusFactory: AbstractFactory {
func createVehicle() -> Vehicle {
return Bus(wheelNumber: 4)
}
}
class MotorBicycleFactory: AbstractFactory {
func createVehicle() -> Vehicle {
return MotorBicycle(wheelNumber: 2)
}
}
AbstractFactory是一個(gè)協(xié)議钝腺,它定義了一個(gè)創(chuàng)建Vehicle的-createVehicle方法抛姑,實(shí)現(xiàn)了該協(xié)議的三個(gè)具體工廠類(lèi)(Concrete Factory)需要實(shí)現(xiàn)該協(xié)議中的-createVehicle方法,分別創(chuàng)建對(duì)應(yīng)的車(chē)輛艳狐。
現(xiàn)在分別創(chuàng)建一個(gè)Car定硝、Bus和MotorBicycle對(duì)象,我們可以用如下代碼實(shí)現(xiàn)毫目,
let car = CarFactory().createVehicle()
let bus = BusFactory().createVehicle()
let motorBicycle = MotorBicycleFactory().createVehicle()
這樣蔬啡,每一種類(lèi)型的車(chē)輛都有其對(duì)應(yīng)的工廠類(lèi)诲侮,當(dāng)我們需要?jiǎng)?chuàng)建一種類(lèi)型的車(chē)輛時(shí),只需調(diào)用其對(duì)應(yīng)的工廠類(lèi)的-createVehicle方法箱蟆。
備注:工廠類(lèi)沟绪,例如CarFactory是負(fù)責(zé)創(chuàng)建Car對(duì)象的,上面的代碼存在一點(diǎn)點(diǎn)的瑕疵空猜,那就是創(chuàng)建多個(gè)Car對(duì)象時(shí)绽慈,也通過(guò)
CarFactory()
多次創(chuàng)建CarFactory對(duì)象,但是它并不涉及到數(shù)據(jù)存儲(chǔ)和業(yè)務(wù)邏輯辈毯,這樣無(wú)疑消耗了額外的內(nèi)存空間坝疼,為了性能考慮,可以將CarFactory漓摩、BusFactory和MotorBicycleFactory定義為單例模式裙士。
可以看出入客,在工廠模式中管毙,有這樣幾個(gè)角色:抽象產(chǎn)品(Abstract Product)、具體產(chǎn)品(Concrete Product)桌硫、抽象工廠(Abstract Factory)夭咬、具體工廠(Concrete Factory)以及客戶(hù)(Consumer),AbstractFactory是工廠模式的核心铆隘,它們之間的關(guān)系如下圖UML所示卓舵,
與簡(jiǎn)單工廠模式相比,工廠模式再也不必?zé)烙谟纺[的代碼膀钠,如果需要制造新的機(jī)車(chē)類(lèi)型掏湾,比如現(xiàn)在需要?jiǎng)?chuàng)建坦克和SUV,為了滿(mǎn)足這樣的需求肿嘲,我們首先創(chuàng)建兩個(gè)繼承于Vehicle的兩個(gè)子類(lèi)Tank和SUV融击,接著分別創(chuàng)建Tank和SUV對(duì)應(yīng)的工廠類(lèi)TankFactory和SUVFactory,使用了這樣的方法雳窟,不會(huì)改動(dòng)原有的代碼結(jié)構(gòu)尊浪,這樣也遵循了“開(kāi)閉原則”。
工廠模式可以滿(mǎn)足大部分需求封救,但是拇涤,但是,重要的但是說(shuō)三遍誉结,但是鹅士,當(dāng)我們將產(chǎn)品細(xì)分為不同的等級(jí)結(jié)構(gòu),例如Car這樣一個(gè)產(chǎn)品可以細(xì)分為發(fā)動(dòng)機(jī)(Engine)惩坑、車(chē)門(mén)(Door)和電池(Battery)等幾個(gè)重要的等級(jí)結(jié)構(gòu)掉盅;而Car本身也有很多類(lèi)型嘱朽,例如奔馳和奧迪,這種情況下怔接,Car有兩種類(lèi)型搪泳,每一種Car都分別有其對(duì)應(yīng)使用的Engine, Door和Battery,如下表所列扼脐,
產(chǎn)品族 / 產(chǎn)品等級(jí) | 奔馳 | 奧迪 |
---|---|---|
發(fā)動(dòng)機(jī)Engine | BenzEngine | AudiEngine |
車(chē)門(mén)Door | BenzDoor | AudiDoor |
電池Battery | BenzBattery | AudiBattery |
這樣細(xì)分下來(lái)岸军,為了使一輛車(chē)可以有效使用,必須保證所用的配件能夠匹配瓦侮,想象一下生產(chǎn)的AudiEngine給Benz用艰赞,BenzDoor給Audi用,真是畫(huà)面太美不敢看肚吏。這時(shí)候給我們生產(chǎn)產(chǎn)品也帶來(lái)了問(wèn)題方妖,因?yàn)楝F(xiàn)在有兩種車(chē)類(lèi)型 - Benz和Audi,每種車(chē)類(lèi)型有三個(gè)重要配件 - Engine罚攀、Door和Battery党觅,如果使用工廠模式生產(chǎn)配件,我們得創(chuàng)建6個(gè)對(duì)應(yīng)的工廠斋泄,即BenzEngineFactory, BenzDoorFactory, BenzBatteryFactory和AudiEngineFactory, AudiDoorFactory, AudiBatteryFactory杯瞻,這無(wú)疑是一個(gè)讓人無(wú)語(yǔ)的方案。所以說(shuō)這種情況下炫掐,工廠模式已經(jīng)滿(mǎn)足不了當(dāng)前的需求魁莉,我們需要進(jìn)行更高一層次的抽象,這時(shí)候“抽象工廠模式”應(yīng)運(yùn)而生募胃。
這里旗唁,筆者在討論生產(chǎn)時(shí)候偷換了概念,文章前段討論簡(jiǎn)單工廠模式(SimpleFactory)和工廠模式(FactoryPattern)時(shí)痹束,工廠生產(chǎn)的產(chǎn)品是Vehicle检疫,現(xiàn)在為了引申出抽象工廠模式(AbstractFactory)將Vehicle的子類(lèi)Car進(jìn)行了細(xì)分,工廠生產(chǎn)產(chǎn)品關(guān)注點(diǎn)不在是Vehicle参袱,而是著重討論生產(chǎn)Car相關(guān)配件 - Engine, Door和Battery电谣。
抽象工廠模式
在進(jìn)一步探討抽象工廠模式之前,我們有必要了解“產(chǎn)品族”和“產(chǎn)品等級(jí)”這兩個(gè)概念抹蚀,所謂產(chǎn)品族剿牺,是指位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中,功能相關(guān)聯(lián)的產(chǎn)品組成的家族环壤。比如奔馳的Engine, Door, Battery組成一個(gè)產(chǎn)品族晒来,Audi的Engine, Door, Battery組成一個(gè)產(chǎn)品族。而這兩個(gè)產(chǎn)品族都來(lái)自于三個(gè)產(chǎn)品等級(jí):Engine, Door和Battery郑现。
生產(chǎn)奔馳的Engine, Door和Battery必須匹配才能組合成有效使用的BenzCar湃崩;同樣生產(chǎn)Audi的Engine, Door和Battery也必須匹配才能組合成可用的AudiCar荧降。也許讓同一個(gè)工廠生產(chǎn)這些配件才能保證合理匹配,例如讓BenzFactory生產(chǎn)奔馳的Engine, Door和Battery攒读,讓AudiFactory生產(chǎn)Audi的Engine, Door和Battery朵诫,采用這樣的做法,我們也避免了工廠模式中為每一種類(lèi)型的配件創(chuàng)建對(duì)應(yīng)的工廠薄扁。既然BenzFactory和AudiFactory都是為了創(chuàng)建一個(gè)產(chǎn)品族剪返,這樣我們可以將BenzFactory和AudiFactory抽象出一個(gè)AbstractFactory,該抽象工廠有三個(gè)方法邓梅,-createEngine, -createDoor, -createBattery脱盲,
如下代碼所示,使用了抽象工廠模式實(shí)現(xiàn)了生產(chǎn)Car的配件日缨,
class Component { // 配件 - 翻譯不好見(jiàn)諒哈
var price: Float = 0.0
}
class Engine: Component {
var speed: Int = 0
var weight: Float = 0.0
}
class BenzEngine: Engine {
}
class AudiEngine: Engine {
}
class Door: Component {
var color: UIColor = UIColor.clearColor()
var hasWindow: Bool = true
}
class BenzDoor: Door {
}
class AudiDoor: Door {
}
class Battery: Component {
var workTime: Int = 0
var lekeage: Bool = false //是否漏電
}
class BenzBattery: Battery {
}
class AudiBattery: Battery {
}
protocol AbstractCarFactory {
func createEngine() -> Engine
func createDoor() -> Door
func createBattery() -> Battery
}
class BenzFactory: AbstractCarFactory {
func createEngine() -> Engine {
return BenzEngine()
}
func createDoor() -> Door {
return BenzDoor()
}
func createBattery() -> Battery {
return BenzBattery()
}
}
class AudiFactory: AbstractCarFactory {
func createEngine() -> Engine {
return AudiEngine()
}
func createDoor() -> Door {
return AudiDoor()
}
func createBattery() -> Battery {
return AudiBattery()
}
}
簡(jiǎn)單描述上面的代碼钱反,
- 定義了一個(gè)基類(lèi)Component,它代表一個(gè)汽車(chē)配件的模型匣距,它有一個(gè)Float類(lèi)型的price屬性面哥;
- 定義三個(gè)子類(lèi)Engine, Door, Battery,它們都繼承自Component墨礁,并且各自定自己的屬性幢竹,例如Battery子類(lèi)定義了workTime(電池工作時(shí)長(zhǎng))和lekeage(是否漏電)耳峦,它們屬于抽象產(chǎn)品(abstract product)的范疇恩静;
- 定義了Benz和Audi兩種車(chē)型Engine, Door, Battery的子類(lèi),分別是BenzEngine, BenzDoor, BenzBattery和AudiEngine, AudiDoor, AudiBattery蹲坷,它屬于具體產(chǎn)品(concrete product)的范疇驶乾;
- 定義核心角色AbstractCarFactory,它是一個(gè)Protocol循签,它內(nèi)部定義了-crateEngine, -createDoor, -createBattery三個(gè)方法级乐,分別用于創(chuàng)建Engine, Door, Battery抽象產(chǎn)品,抽象工廠并不創(chuàng)建具體的產(chǎn)品县匠;
- 定義BenzFactory和AudiFactory兩個(gè)具體工廠风科,它們實(shí)現(xiàn)AbstractCarFactory協(xié)議,負(fù)責(zé)創(chuàng)建具體的產(chǎn)品對(duì)象乞旦,也就是說(shuō)抽象工廠定義接口贼穆,具體工廠實(shí)現(xiàn)接口邏輯。
分析總結(jié)兰粉,抽象工廠模式與工廠模式一樣故痊,都包含如下4個(gè)角色,即玖姑,
- 抽象工廠
- 具體工廠
- 抽象產(chǎn)品
- 具體產(chǎn)品
區(qū)別在于愕秫,工廠模式只生產(chǎn)一種單一的產(chǎn)品慨菱,而抽象工廠模式生產(chǎn)多種類(lèi)型的產(chǎn)品,準(zhǔn)確來(lái)說(shuō)戴甩,抽象工廠模式可以生產(chǎn)一個(gè)產(chǎn)品族符喝。
它們之間的關(guān)系如下圖UML所示,
此時(shí)我們可以這樣創(chuàng)建一個(gè)Benz汽車(chē)對(duì)象甜孤,如下代碼所示洲劣,
class Car {
var engine: Engine
var door: Door
var battery: Battery
init(engine: Engine, door: Door, battery: Battery) {
self.engine = engine
self.door = door
self.battery = battery
}
}
func makeCar(carFactory: AbstractCarFactory) -> Car {
let engine = carFactory.createEngine()
let door = carFactory.createDoor()
let battery = carFactory.createBattery()
let car = Car(engine: engine, door: door, battery: battery)
return car
}
let benzCar = makeCar(BenzFactory())
簡(jiǎn)單解釋上述代碼,首先新定義了一個(gè)類(lèi)Car课蔬,它包含Engine, Door, Battery三個(gè)屬性囱稽,并定義了-init初始化方法;接著定義了-makeCar方法二跋,它接受的參數(shù)是AbstractCarFactory战惊,返回一個(gè)Car對(duì)象;我們需要?jiǎng)?chuàng)建benzCar扎即,直接為-makeCar方法參數(shù)設(shè)置為BenzFactory對(duì)象即可吞获。
筆者冒泡:本文在兩臺(tái)不同電腦寫(xiě)作,因?yàn)橄到y(tǒng)原因谚鄙,Mac Book Pro不能使用ArgoUML各拷,所以只能換個(gè)方式畫(huà)UML類(lèi)圖,所以導(dǎo)致抽象工廠模式的UML圖和之前的畫(huà)風(fēng)不一樣闷营。因?yàn)闀r(shí)間有限烤黍,所以也重新畫(huà)圖,導(dǎo)致風(fēng)格不統(tǒng)一傻盟,忘讀者見(jiàn)諒速蕊。
Objective-C SDK中的抽象工廠模式
在Objecitve-C SDK中,NSNumber是我們經(jīng)常使用的類(lèi)娘赴,我們可以使用NSNumber創(chuàng)建不同類(lèi)型的數(shù)據(jù)规哲,如下代碼,
NSNumber *integerValue = [NSNumber numberWithInteger:1000];
NSNumber *boolValue = [NSNumber numberWithBool: YES];
...
實(shí)際上NSnumber是一個(gè)類(lèi)族诽表,大概就是文章前面提到的產(chǎn)品族這樣的概念吧唉锌,它包含Char, NSInteger, Bool, Short...等,如果沒(méi)有NSNumber提供的抽象工廠模式來(lái)創(chuàng)建對(duì)象竿奏,那么對(duì)于我們編碼來(lái)說(shuō)簡(jiǎn)直就是噩夢(mèng)袄简。
NSNumber本身就是一個(gè)抽象工廠,它提供了不同的接口用于創(chuàng)建不同類(lèi)型數(shù)據(jù)對(duì)應(yīng)的對(duì)象议双,至于創(chuàng)建對(duì)象的細(xì)節(jié)痘番,則交付給實(shí)現(xiàn)NSNumber抽象接口的具體工廠。
微信公眾號(hào)
歡迎關(guān)注本人微信公眾號(hào),請(qǐng)掃描下方二維碼汞舱,