創(chuàng)建者模式-建造者模式(The Builder Pattern)

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

建造者模式(The Builder Pattern)

建造者模式用來(lái)將對(duì)象的配置從創(chuàng)建中分離出來(lái)列粪。請(qǐng)求組件有配置數(shù)據(jù)并將它傳遞給中間人-建造者-它負(fù)責(zé)創(chuàng)建代表組件的對(duì)象薇宠。建造者模式它可以將復(fù)雜對(duì)象的建造過(guò)程抽象出來(lái)(抽象類別)肖油,使這個(gè)抽象過(guò)程的不同實(shí)現(xiàn)方法可以構(gòu)造出不同表現(xiàn)(屬性)的對(duì)象憨愉。


示例工程

OS X Command Line Tool工程:

Food.swift

class Burger {
    
    let customerName:String
    let veggieProduct:Bool
    let patties:Int
    let pickles:Bool
    let mayo:Bool
    let ketchup:Bool
    let lettuce:Bool
    let cook:Cooked
    
    enum Cooked : String {
        case RARE = "Rare"
        case NORMAL = "Normal"
        case WELLDONE = "Well Done"
    }
    
    init(name:String, veggie:Bool, patties:Int, pickles:Bool, mayo:Bool,
        ketchup:Bool, lettuce:Bool, cook:Cooked) {
        self.customerName = name
        self.veggieProduct = veggie
        self.patties = patties
        self.pickles = pickles
        self.mayo = mayo
        self.ketchup = ketchup
        self.lettuce = lettuce
        self.cook = cook
    }
    
    func printDescription() {
        print("Name \(self.customerName)")
        print("Veggie: \(self.veggieProduct)")
        print("Patties: \(self.patties)")
        print("Pickles: \(self.pickles)")
        print("Mayo: \(self.mayo)")
        print("Ketchup: \(self.ketchup)")
        print("Lettuce: \(self.lettuce)")
        print("Cook: \(self.cook.rawValue)")
    }
}

接下來(lái)main.swift

main.swift

let order = Burger(name: "Joe", veggie: false, patties: 2, pickles: true,
    mayo: true, ketchup: true, lettuce: true, cook: Burger.Cooked.NORMAL)
order.printDescription()

運(yùn)行程序:

Name Joe
Veggie: false
Patties: 2
Pickles: true
Mayo: true
Ketchup: true
Lettuce: true
Cook: Normal

理解建造者模式解決的問(wèn)題

當(dāng)一個(gè)對(duì)象需要大量的配置數(shù)據(jù)的時(shí)候烦绳,建造者模式出現(xiàn)了。在上面的例子中莱衩,Burger類的初始化方法就要求每一個(gè)方面的配置數(shù)據(jù)爵嗅。下面的是虛構(gòu)的餐館預(yù)定漢堡包過(guò)程:

  1. 服務(wù)員問(wèn)顧客的姓名
  2. 服務(wù)員問(wèn)顧客是否需要素食
  3. 服務(wù)員問(wèn)顧客是否要定做漢堡包
  4. 服務(wù)員問(wèn)顧客是否要升級(jí)買(mǎi)一個(gè)額外的肉餅

上面只有4個(gè)步驟,但卻拋出了一些問(wèn)題笨蚁。其實(shí)我們?cè)趧?chuàng)建Burger對(duì)象的時(shí)候是這樣的:

main.swift

// Step 1 - Ask for name
let name = "Joe"
// Step 2 - Is veggie meal required?
let veggie = false
// Step 3 - Customize burger?
let pickles = true
let mayo = false
let ketchup = true
let lettuce = true
// Step 4 - Buy additional patty?
let patties = 2
let cooked = Burger.Cooked.NORMAL

let order = Burger(name: name, veggie: veggie, patties: patties, pickles: pickles, mayo: mayo, ketchup: ketchup, lettuce: lettuce, cook: cooked)
order.printDescription()

Burger類的初始化方法要求請(qǐng)求組件知道默認(rèn)的值當(dāng)顧客不想改變Burger的配置的時(shí)候睹晒。每一個(gè)請(qǐng)求組件都必須知道這個(gè)事情趟庄,那就意味著如果改變一個(gè)默認(rèn)的值,那么就必須改變每一個(gè)請(qǐng)求組件伪很。


理解建造者模式

建造者模式解決這個(gè)問(wèn)題通過(guò)引出一個(gè)中間人-建造者-在請(qǐng)求組件和需要?jiǎng)?chuàng)建的對(duì)象之間戚啥。



實(shí)現(xiàn)建造者模式

1. 定義創(chuàng)建者類

首先,就是創(chuàng)建建造者類锉试,建造者類提供了Burger類參數(shù)的默認(rèn)值并且允許請(qǐng)求組件去改變這些值猫十。

Builder.swift

class BurgerBuilder {
    private var veggie  = false
    private var pickles = true
    private var mayo    = true
    private var ketchup = true
    private var lettuce = true
    private var cooked  = Burger.Cooked.NORMAL
    private var patties = 2
    
    func setVeggie(choice: Bool)  { self.veggie  = choice }
    func setPickles(choice: Bool) { self.pickles = choice }
    func setMayo(choice: Bool)    { self.mayo    = choice }
    func setKetchup(choice: Bool) { self.ketchup = choice }
    func setLettuce(choice: Bool) { self.lettuce = choice }
    func setCooked(choice: Burger.Cooked) { self.cooked = choice }
    func addPatty(choice: Bool)   { self.patties = choice ? 3 : 2 }
    
    func buildObject() -> Burger{
        return Burger(name: name, veggie: veggie, patties: patties, pickles: pickles, mayo: mayo, ketchup: ketchup, lettuce: lettuce, cook: cooked)
    }
    
}

2. 使用建造者

main.swift

var builder = BurgerBuilder()
// Step 1 - Ask for name
let name = "Joe"
// Step 2 - Is veggie meal required?
builder.setVeggie(false)
// Step 3 - Customize burger?
builder.setMayo(false)
builder.setCooked(Burger.Cooked.WELLDONE)
// Step 4 - Buy additional patty?
builder.addPatty(false)
let order = builder.buildObject(name)
order.printDescription()

運(yùn)行程序,輸出:

Name Joe
Veggie: false
Patties: 2
Pickles: true
Mayo: false
Ketchup: true
Lettuce: true
Cook: Well Done

建造者模式的變形

你可以將建造者模式和其他模式結(jié)合起來(lái)呆盖,一般是和工廠方法模式和抽象工廠模式拖云。用得最多的就是定義復(fù)數(shù)的建造者并且讓它們都實(shí)現(xiàn)工廠方法模式。

Builder.swift

enum Burgers {
    case STANDARD
    case BIGBURGER
    case SUPERVEGGIE
}

class BurgerBuilder {
    private var veggie  = false
    private var pickles = true
    private var mayo    = true
    private var ketchup = true
    private var lettuce = true
    private var cooked  = Burger.Cooked.NORMAL
    private var patties = 2
    private var bacon   = true
    
    private init() {
        // do nothing
    }
    
    func setVeggie(choice: Bool)  {
        self.veggie = choice
        if (choice) {
            self.bacon = false
        }
    }
    func setPickles(choice: Bool) { self.pickles = choice }
    func setMayo(choice: Bool)    { self.mayo    = choice }
    func setKetchup(choice: Bool) { self.ketchup = choice }
    func setLettuce(choice: Bool) { self.lettuce = choice }
    func setCooked(choice: Burger.Cooked) { self.cooked = choice }
    func addPatty(choice: Bool)   { self.patties = choice ? 3 : 2 }
    func setBacon(choice: Bool)   { self.bacon   = choice }
    
    func buildObject(name:String) -> Burger{
        return Burger(name: name, veggie: veggie, patties: patties, pickles: pickles, mayo: mayo, ketchup: ketchup, lettuce: lettuce, cook: cooked,bacon: bacon)
    }
    
    class func getBuilder(burgerType:Burgers) -> BurgerBuilder {
        var builder:BurgerBuilder
        switch (burgerType) {
            case .BIGBURGER: builder   = BigBurgerBuilder()
            case .SUPERVEGGIE: builder = SuperVeggieBurgerBuilder()
            case .STANDARD: builder    = BurgerBuilder()
        }
        return builder
    }
    
}

class BigBurgerBuilder : BurgerBuilder {
    private override init() {
        super.init()
        self.patties = 4
        self.bacon = false
    }
        
    override func addPatty(choice: Bool) {
        fatalError("Cannot add patty to Big Burger")
    }
}

class SuperVeggieBurgerBuilder : BurgerBuilder {
    private override init() {
        super.init()
        self.veggie = true
        self.bacon = false
    }
        
    override func setVeggie(choice: Bool) {
        // do nothing - always veggie
    }
        
    override func setBacon(choice: Bool) {
        fatalError("Cannot add bacon to this burger")
    }
}

接著是:

main.swift

// Step 1 - Ask for name
let name = "Joe"

// Step 2 - Select a Product
let builder = BurgerBuilder.getBuilder(Burgers.BIGBURGER)

// Step 3 - Customize burger?
builder.setMayo(false)
builder.setCooked(Burger.Cooked.WELLDONE)

let order = builder.buildObject(name)
order.printDescription()

運(yùn)行程序应又,輸出:

Name Joe
Veggie: false
Patties: 4
Pickles: true
Mayo: false
Ketchup: true
Lettuce: true
Cook: Well Done

Cocoa中的建造者模式

Cocoa中最常用的使用的建造者模式的類就是 NSDateComponents類宙项,NSDateComponents類允許請(qǐng)求組件設(shè)置值來(lái)創(chuàng)建 NSDate類。請(qǐng)看下面例子:

import Foundation
var builder = NSDateComponents()

builder.hour = 10
builder.day = 6
builder.month = 9
builder.year = 1940
builder.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)

var date = builder.date
print(date!)

運(yùn)行程序株扛,輸出:

1940-09-06 01:00:00 +0000
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尤筐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子洞就,更是在濱河造成了極大的恐慌盆繁,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旬蟋,死亡現(xiàn)場(chǎng)離奇詭異油昂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)咖为,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)秕狰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人躁染,你說(shuō)我怎么就攤上這事鸣哀。” “怎么了吞彤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵我衬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我饰恕,道長(zhǎng)挠羔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任埋嵌,我火速辦了婚禮破加,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘雹嗦。我一直安慰自己范舀,他們只是感情好合是,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著锭环,像睡著了一般聪全。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辅辩,一...
    開(kāi)封第一講書(shū)人閱讀 51,245評(píng)論 1 299
  • 那天难礼,我揣著相機(jī)與錄音,去河邊找鬼玫锋。 笑死蛾茉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的景醇。 我是一名探鬼主播臀稚,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼三痰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起窜管,我...
    開(kāi)封第一講書(shū)人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤散劫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后幕帆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體获搏,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年失乾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了常熙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碱茁,死狀恐怖裸卫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纽竣,我是刑警寧澤墓贿,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站蜓氨,受9級(jí)特大地震影響聋袋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜穴吹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一幽勒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧港令,春花似錦啥容、人聲如沸棘钞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宜猜。三九已至,卻和暖如春硝逢,著一層夾襖步出監(jiān)牢的瞬間姨拥,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工渠鸽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叫乌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓徽缚,卻偏偏與公主長(zhǎng)得像憨奸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凿试,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理排宰,服務(wù)發(fā)現(xiàn),斷路器那婉,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • 沒(méi)有人買(mǎi)車會(huì)只買(mǎi)一個(gè)輪胎或者方向盤(pán)板甘,大家買(mǎi)的都是一輛包含輪胎、方向盤(pán)和發(fā)動(dòng)機(jī)等多個(gè)部件的完整汽車详炬。如何將這些部件組...
    justCode_閱讀 1,838評(píng)論 1 6
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)盐类、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,098評(píng)論 4 62
  • 在公園散步 在樹(shù)下談心 在商場(chǎng)閑逛 手拉著手 喜歡你騎車載我回家 摟著你的腰 這畫(huà)面曾經(jīng)是我羨慕的 羨慕著別人一起...
    追求快樂(lè)閱讀 315評(píng)論 0 1
  • 在以前的博文中談了自己對(duì)用戶成熟度的一些看法以及不成熟用戶的一些表現(xiàn)呛谜。最近回了一趟老家在跳,再度讓我思考用戶成熟度的問(wèn)...
    馬虎眼閱讀 1,006評(píng)論 0 19