創(chuàng)建者模式-抽象工廠模式(The Abstract Factory Pattern)

本文大部分內(nèi)容翻譯至《Pro Design Pattern In Swift》By Adam Freeman,一些地方做了些許修改性芬,并將代碼升級到了Swift2.0,翻譯不當(dāng)之處望多包涵峡眶。

抽象工廠模式(The Abstract Factory Pattern)

抽象工廠模式提供了一種方式,可以將一組具有同一主題的單獨(dú)的工廠封裝起來植锉。在正常使用中辫樱,客戶端程序需要創(chuàng)建抽象工廠的具體實(shí)現(xiàn),然后使用抽象工廠作為接口來創(chuàng)建這一主題的具體對象俊庇∈ㄊ睿客戶端程序不需要知道(或關(guān)心)它從這些內(nèi)部的工廠方法中獲得對象的具體類型,因?yàn)榭蛻舳顺绦騼H使用這些對象的通用接口辉饱。抽象工廠模式將一組對象的實(shí)現(xiàn)細(xì)節(jié)與他們的一般使用分離開來搬男。


示例工程

OS X Command Line Tool 工程:

Floorplans.swift

protocol Floorplan {
    var seats:Int { get }
    var enginePosition:EngineOption { get }
}

enum EngineOption : String {
    case FRONT = "Front"
    case MID = "Mid"
}

class ShortFloorplan: Floorplan {
    var seats = 2
    var enginePosition = EngineOption.MID
}

class StandardFloorplan: Floorplan {
    var seats = 4
    var enginePosition = EngineOption.FRONT
}

class LongFloorplan: Floorplan {
    var seats = 8
    var enginePosition = EngineOption.FRONT
}

定義了一個協(xié)議Floorplan 代表車的構(gòu)建,枚舉EngineOption代表引擎的位置等彭沼。接著我們看另一個相關(guān)Suspension(汽車懸架):

Suspension.swift

protocol Suspension {
    var suspensionType:SuspensionOption { get }
}

enum SuspensionOption : String {
    case STANDARD = "Standard"
    case SPORTS = "Firm"
    case SOFT = "Soft"
}

class RoadSuspension : Suspension {
    var suspensionType = SuspensionOption.STANDARD
}

class OffRoadSuspension : Suspension {
    var suspensionType = SuspensionOption.SOFT
}

class RaceSuspension : Suspension {
    var suspensionType = SuspensionOption.SPORTS
}

接下來是Drivetrains(汽車動力傳動系統(tǒng)):

Drivetrains.swift

protocol Drivetrain {
    var driveType:DriveOption { get }
}

enum DriveOption : String {
    case FRONT = "Front"
        case REAR = "Rear"
        case ALL = "4WD"
}

class FrontWheelDrive : Drivetrain {
    var driveType = DriveOption.FRONT
}

class RearWheelDrive : Drivetrain {
    var driveType = DriveOption.REAR
}

class AllWheelDrive : Drivetrain {
    var driveType = DriveOption.ALL
}

最后我們創(chuàng)建CarsParts.swift文件:

CarsParts.swift

enum Cars: String {
    case COMPACT = "VW Golf"
    case SPORTS = "Porsche Boxter"
    case SUV = "Cadillac Escalade"
}

struct Car {
    var carType:Cars
    var floor:Floorplan
    var suspension:Suspension
    var drive:Drivetrain
    
    func printDetails() {
        print("Car type: \(carType.rawValue)")
        print("Seats: \(floor.seats)")
        print("Engine: \(floor.enginePosition.rawValue)")
        print("Suspension: \(suspension.suspensionType.rawValue)")
        print("Drive: \(drive.driveType.rawValue)")
    }
}

理解抽象工廠模式解決的問題

工廠方法模式允許請求組件不需要知道各種細(xì)節(jié)而獲得一個實(shí)現(xiàn)類的實(shí)例缔逛, 而抽象工廠解決的問題有點(diǎn)類似但是一組并非實(shí)現(xiàn)同一個協(xié)議或者繼承相同基類的相關(guān)的對象。



我們修改main.swift

main.swift

var car = Car(carType: Cars.SPORTS,
    floor: ShortFloorplan(),
    suspension: RaceSuspension(),
    drive: RearWheelDrive())

car.printDetails()

運(yùn)行程序姓惑,得到下面輸出:

Car type: Porsche Boxter
Seats: 2
Engine: Mid
Suspension: Firm
Drive: Rear

理解抽象工廠模式

抽象工廠模式和工廠方法模式都是為了解決同一個問題褐奴,但是抽象工廠模式是用在創(chuàng)建一組對象,并且這些對象并沒有實(shí)現(xiàn)同一個協(xié)議或者繼承相同的基類于毙。在示例中敦冬,構(gòu)建一個Car結(jié)構(gòu)體需要三個對象,并且每一個對象實(shí)現(xiàn)的不同的協(xié)議:Floorplan, Suspension, Drivetrain 唯沮。

抽象工廠模式用合并的方式來解決散亂的對象選擇邏輯問題脖旱,用只向請求組件提供協(xié)議來解決依賴問題。


  1. 提供一個抽象工廠類介蛉,定義了一個返回一個協(xié)議實(shí)例或者基類實(shí)例的方法夯缺。
  2. 抽象工廠方法檢查調(diào)用者的請求并選擇一個具體工廠類,這個工廠類就是實(shí)現(xiàn)了工廠方法模式的類甘耿。具體工廠類的實(shí)例就被創(chuàng)建了并返回給了調(diào)用者。
  3. 調(diào)用者調(diào)用具體工廠類的的工廠方法竿滨。
  4. 實(shí)現(xiàn)類被初始化并提供給調(diào)用者佳恬。

實(shí)現(xiàn)抽象工廠模式

  • 創(chuàng)建抽象工廠

Abstract.swift

class CarFactory {
    func createFloorplan() -> Floorplan {
        fatalError("Not implemented")
    }
    
    func createSuspension() -> Suspension {
        fatalError("Not implemented")
    }
    
    func createDrivetrain() -> Drivetrain {
        fatalError("Not implemented")
    }
}
  • 創(chuàng)建具體工廠

Concrete.swift

class CompactCarFactory : CarFactory {
    override func createFloorplan() -> Floorplan {
        return StandardFloorplan()
    }
    override func createSuspension() -> Suspension {
        return RoadSuspension()
    }
    override func createDrivetrain() -> Drivetrain {
    return FrontWheelDrive()
    }
}

class SportsCarFactory : CarFactory {
    override func createFloorplan() -> Floorplan {
        return ShortFloorplan()
        }
    override func createSuspension() -> Suspension {
        return RaceSuspension()
        }
    override func createDrivetrain() -> Drivetrain {
        return RearWheelDrive()
        }
}
class SUVCarFactory : CarFactory {
    override func createFloorplan() -> Floorplan {
        return LongFloorplan()
        }
    override func createSuspension() -> Suspension {
        return OffRoadSuspension()
        }
    override func createDrivetrain() -> Drivetrain {
        return AllWheelDrive()
        }
}
  • 完成抽象工廠

Abstract.swift

class CarFactory {
    func createFloorplan() -> Floorplan {
        fatalError("Not implemented")
    }
    
    func createSuspension() -> Suspension {
        fatalError("Not implemented")
    }
    
    func createDrivetrain() -> Drivetrain {
        fatalError("Not implemented")
    }
    
    final class func getFactory(car:Cars) -> CarFactory? {
        var factory:CarFactory?
        switch (car) {
        case .COMPACT:
            factory = CompactCarFactory()
        case .SPORTS:
            factory = SportsCarFactory()
        case .SUV:
            factory = SUVCarFactory()
        }
        return factory
    }
}
  • 消費(fèi)抽象工廠模式

最后一步就是更新Car對象捏境,讓它從抽象工廠中獲得產(chǎn)品對象。

main.swift

let factory = CarFactory.getFactory(Cars.SPORTS)
if (factory != nil) {
    let car = Car(carType: Cars.SPORTS,
    floor: factory!.createFloorplan(),
    suspension: factory!.createSuspension(),
    drive: factory!.createDrivetrain())
    car.printDetails()
}

運(yùn)行程序毁葱,得到和上面一樣的結(jié)果:

Car type: Porsche Boxter
Seats: 2
Engine: Mid
Suspension: Firm
Drive: Rear

我們可以看出main.swift和獨(dú)立的產(chǎn)品類之間沒有了依賴垫言。我們可以直接改變具體工廠類而不修改main.swift。

Concrete.swift

...
class SportsCarFactory : CarFactory {
    override func createFloorplan() -> Floorplan {
        return ShortFloorplan()
        }
    override func createSuspension() -> Suspension {
        return RaceSuspension()
        }
    override func createDrivetrain() -> Drivetrain {
        return AllWheelDrive()
        }
}
...

再次運(yùn)行程序:

Car type: Porsche Boxter
Seats: 2
Engine: Mid
Suspension: Firm
Drive: 4WD

抽象工廠模式的變形

  • 隱藏抽象工廠類

第一個最普通的變形就是將抽象工廠模式的實(shí)現(xiàn)隱藏結(jié)構(gòu)體或者類中倾剿。在本例中顯然就是Car類筷频。

CarParts.swift

...
struct Car {
    var carType:Cars
    var floor:Floorplan
    var suspension:Suspension
    var drive:Drivetrain
    
    init(carType:Cars) {
        let concreteFactory = CarFactory.getFactory(carType)
        self.floor = concreteFactory!.createFloorplan()
        self.suspension = concreteFactory!.createSuspension()
        self.drive = concreteFactory!.createDrivetrain()
        self.carType = carType
    }
    
    func printDetails() {
        print("Car type: \(carType.rawValue)")
        print("Seats: \(floor.seats)")
        print("Engine: \(floor.enginePosition.rawValue)")
        print("Suspension: \(suspension.suspensionType.rawValue)")
        print("Drive: \(drive.driveType.rawValue)")
    }
}

這樣一來,main.swift就變得更簡單了:

main.swift

let car = Car(carType: Cars.SPORTS)
car.printDetails()
  • 具體工廠類實(shí)現(xiàn)單例模式

另一個很普遍的變形就是具體工廠類實(shí)現(xiàn)單例模式前痘。

class CarFactory {
    
    func createFloorplan() -> Floorplan {
        fatalError("Not implemented")
    }
    
    func createSuspension() -> Suspension {
        fatalError("Not implemented")
    }
    
    func createDrivetrain() -> Drivetrain {
        fatalError("Not implemented")
    }
    
    final class func getFactory(car:Cars) -> CarFactory? {
        var factory:CarFactory
        switch (car) {
        case .COMPACT:
            factory = CompactCarFactory.sharedInstance
        case .SPORTS:
            factory = SportsCarFactory.sharedInstance
        case .SUV:
            factory = SUVCarFactory.sharedInstance
        }
        return factory
    }
}

接下來修改:

Concrete.swift

class CompactCarFactory : CarFactory {
    
    private override init(){}
    
    static let sharedInstance = CompactCarFactory()
    
    override func createFloorplan() -> Floorplan {
        return StandardFloorplan()
    }
    
    override func createSuspension() -> Suspension {
        return RoadSuspension()
    }
    
    override func createDrivetrain() -> Drivetrain {
        return FrontWheelDrive()
    }
}

class SportsCarFactory : CarFactory {
    
    private override init(){}
    
    static let sharedInstance = SportsCarFactory()
    
    override func createFloorplan() -> Floorplan {
        return ShortFloorplan()
    }
    override func createSuspension() -> Suspension {
        return RaceSuspension()
    }
    override func createDrivetrain() -> Drivetrain {
        return AllWheelDrive()
    }
}

class SUVCarFactory : CarFactory {
    
    private override init(){}
    
    static let sharedInstance = SUVCarFactory()
    
    override func createFloorplan() -> Floorplan {
        return LongFloorplan()
    }
    override func createSuspension() -> Suspension {
        return OffRoadSuspension()
    }
    override func createDrivetrain() -> Drivetrain {
        return AllWheelDrive()
    }
}
  • 為實(shí)現(xiàn)類應(yīng)用原型模式

最重要的是為實(shí)現(xiàn)類去應(yīng)用原型模式而非具體工廠類凛捏。

Suspersion.swift

import Foundation

protocol Suspension {
    var suspensionType:SuspensionOption { get }
}

enum SuspensionOption : String {
    case STANDARD = "Standard"
    case SPORTS = "Firm"
    case SOFT = "Soft"
}
***

class RoadSuspension :NSObject, NSCopying,Suspension {

    var suspensionType = SuspensionOption.STANDARD
        
    static let sharedInstance = RoadSuspension()
        
    func copyWithZone(zone: NSZone) -> AnyObject {
        return RoadSuspension()
            
    }
        
    class func getInstance() -> Suspension {
        return sharedInstance.copy() as! Suspension
        
    }
    
}

class OffRoadSuspension :NSObject, NSCopying, Suspension {
    
    var suspensionType = SuspensionOption.SOFT
    
    static let sharedInstance = OffRoadSuspension()
    
    func copyWithZone(zone: NSZone) -> AnyObject {
        return OffRoadSuspension()
        
    }
    
    class func getInstance() -> Suspension {
        return sharedInstance.copy() as! Suspension
        
    }
}

class RaceSuspension :NSObject, NSCopying,  Suspension {
    
    var suspensionType = SuspensionOption.SPORTS
    
    static let sharedInstance = RaceSuspension()
    
    func copyWithZone(zone: NSZone) -> AnyObject {
        return RaceSuspension()
        
    }
    
    class func getInstance() -> Suspension {
        return sharedInstance.copy() as! Suspension
        
    }
}

接下來修改:

Concrete.swift

class CompactCarFactory : CarFactory {
    
    private override init(){}
    
    static let sharedInstance = CompactCarFactory()
    
    override func createFloorplan() -> Floorplan {
        return StandardFloorplan()
    }
    
    override func createSuspension() -> Suspension {
        return RoadSuspension.getInstance()
    }
    
    override func createDrivetrain() -> Drivetrain {
        return FrontWheelDrive()
    }
}

class SportsCarFactory : CarFactory {
    
    private override init(){}
    
    static let sharedInstance = SportsCarFactory()
    
    override func createFloorplan() -> Floorplan {
        return ShortFloorplan()
    }
    override func createSuspension() -> Suspension {
        return RaceSuspension.getInstance()
    }
    override func createDrivetrain() -> Drivetrain {
        return AllWheelDrive()
    }
}

class SUVCarFactory : CarFactory {
    
    private override init(){}
    
    static let sharedInstance = SUVCarFactory()
    
    override func createFloorplan() -> Floorplan {
        return LongFloorplan()
    }
    override func createSuspension() -> Suspension {
        return OffRoadSuspension.getInstance()
    }
    override func createDrivetrain() -> Drivetrain {
        return AllWheelDrive()
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芹缔,隨后出現(xiàn)的幾起案子坯癣,更是在濱河造成了極大的恐慌,老刑警劉巖最欠,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件示罗,死亡現(xiàn)場離奇詭異,居然都是意外死亡芝硬,警方通過查閱死者的電腦和手機(jī)蚜点,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拌阴,“玉大人绍绘,你說我怎么就攤上這事∑す伲” “怎么了脯倒?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長捺氢。 經(jīng)常有香客問我藻丢,道長,這世上最難降的妖魔是什么摄乒? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任悠反,我火速辦了婚禮,結(jié)果婚禮上馍佑,老公的妹妹穿的比我還像新娘斋否。我一直安慰自己,他們只是感情好拭荤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布茵臭。 她就那樣靜靜地躺著,像睡著了一般舅世。 火紅的嫁衣襯著肌膚如雪旦委。 梳的紋絲不亂的頭發(fā)上奇徒,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天,我揣著相機(jī)與錄音缨硝,去河邊找鬼摩钙。 笑死,一個胖子當(dāng)著我的面吹牛查辩,可吹牛的內(nèi)容都是我干的胖笛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宜岛,長吁一口氣:“原來是場噩夢啊……” “哼长踊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谬返,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤之斯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后遣铝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體佑刷,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年酿炸,在試婚紗的時候發(fā)現(xiàn)自己被綠了瘫絮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡填硕,死狀恐怖麦萤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扁眯,我是刑警寧澤壮莹,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站姻檀,受9級特大地震影響命满,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绣版,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一胶台、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杂抽,春花似錦诈唬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春愚屁,著一層夾襖步出監(jiān)牢的瞬間济竹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工霎槐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人梦谜。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓丘跌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親唁桩。 傳聞我的和親對象是個殘疾皇子闭树,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評論 2 354

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