博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
读《Design-Patterns-by-Tutorials》笔记——Builder Pattern
阅读量:6472 次
发布时间:2019-06-23

本文共 3844 字,大约阅读时间需要 12 分钟。

构造器模式允许一步一步的创建一个复杂的对象而不是一次创建完成。这个模式包括三个主要类型,UML 图如下:

  1. Director接收输入并且和 builder 协调。Director通常是一个 view controller或者是view controller 使用的帮助类。
  2. Product是被创建的复杂对象,可以是一个class 或者 struct,取决于是否想要引用语义。通常是一个 model。
  3. Builder接收一步步输入并且控制 product 的创建。经常是一个 class,可以通过引用被复用。

When should you use it?

当我们想要使用一系列步骤创建一个复杂对象时可以使用构造器模式。当一个 product 需要几个部分输入时这个模式工作尤其优秀。构造器将如何创建product 的输入抽象并且以 director 想要提供输入的任何顺序接收他们。比如:我们可以使用这个模式去实现一个”汉堡构造器”。product 可能是一个humburger对象,它有一些输入,比如:肉,配料和胡椒酱。director 可能是一个employee对象,这个对象知道如何做汉堡,或者可能是一个 view controller,它可以接收用户的输入。 汉堡构造器可以以任意的顺序接收肉的选择,配料和胡椒酱并且根据需求创建一个汉堡。

Playground example

Builder是一个创造型模式。这是因为构造器模式是关于创造复杂产品的一个模式。这里我们将实现一个汉堡构造器的例子。 首先,我们先来创建一个** product**:

// MARK: - Productpublic struct Hamburger {  public let meat: Meat  public let sauce: Sauces  public let toppings: Toppings}extension Hamburger: CustomStringConvertible {  public var description: String {    return meat.rawValue + " burger"  }}public enum Meat: String {  case beef  case chicken  case kitten  case tofu}public struct Sauces: OptionSet {  public static let mayonnaise = Sauces(rawValue: 1 << 0)  public static let mustard = Sauces(rawValue: 1 << 1)  public static let ketchup = Sauces(rawValue: 1 << 2)  public static let secret = Sauces(rawValue: 1 << 3)    public let rawValue: Int  public init(rawValue: Int) {    self.rawValue = rawValue  }}public struct Toppings: OptionSet {  public static let cheese = Toppings(rawValue: 1 << 0)  public static let lettuce = Toppings(rawValue: 1 << 1)  public static let pickles = Toppings(rawValue: 1 << 2)  public static let tomatoes = Toppings(rawValue: 1 << 3)    public let rawValue: Int  public init(rawValue: Int) {    self.rawValue = rawValue  }}复制代码

接下来,我们定义一个builder

// MARK: - Builderpublic class HamburgerBuilder {    public enum Error: Swift.Error {    case soldOut  }    public private(set) var meat: Meat = .beef  public private(set) var sauces: Sauces = []  public private(set) var toppings: Toppings = []    private var soldOutMeats: [Meat] = [.kitten]    public func addSauces(_ sauce: Sauces) {    sauces.insert(sauce)  }    public func removeSauces(_ sauce: Sauces) {    sauces.remove(sauce)  }    public func addToppings(_ topping: Toppings) {    toppings.insert(topping)  }    public func removeToppings(_ topping: Toppings) {    toppings.remove(topping)  }    public func setMeat(_ meat: Meat) throws {    guard isAvailable(meat) else { throw Error.soldOut }    self.meat = meat  }    public func isAvailable(_ meat: Meat) -> Bool {    return !soldOutMeats.contains(meat)  }    public func build() -> Hamburger {    return Hamburger(meat: meat,                     sauce: sauces,                     toppings: toppings)  }}复制代码

接下来,我们添加director

// MARK: - Directorpublic class Employee {    public func createCombo1() throws -> Hamburger {    let builder = HamburgerBuilder()    try builder.setMeat(.beef)    builder.addSauces(.secret)    builder.addToppings([.lettuce, .tomatoes, .pickles])    return builder.build()  }    public func createKittenSpecial() throws -> Hamburger {    let builder = HamburgerBuilder()    try builder.setMeat(.kitten)    builder.addSauces(.mustard)    builder.addToppings([.lettuce, .tomatoes])    return builder.build()  }}复制代码

接下来测试一下:

// MARK: - Examplelet burgerFlipper = Employee()if let combo1 = try? burgerFlipper.createCombo1() {  print("Nom nom " + combo1.description)}if let kittenBurger = try?  burgerFlipper.createKittenSpecial() {  print("Nom nom nom " + kittenBurger.description)  } else {  print("Sorry, no kitten burgers here... :[")}复制代码

可以看到控制台打印:

Nom nom beef burgerSorry, no kitten burgers here... :[复制代码

What should you be careful about?

构造器模式对需要多次输入创建复杂对象工作起来很好。如果你的 product 没有几个输入或者不能一步步被创建,构造器可能不适合,便利构造器可能更适合。

Tutorial project

这里我们继续为以前的 app 增加功能,这节我们将使用构造器模式来添加创建新的QuestionGroup功能。实现效果如下:

预告

下节我们讲学习 MVVM 设计模式,将会开启一个新的工程。这个工程就到此为止了。

转载地址:http://kovko.baihongyu.com/

你可能感兴趣的文章
【转载】如何发送和接收 Windows Phone 的 Raw 通知
查看>>
WCF简要介绍
查看>>
NYOJ 97
查看>>
poj2378
查看>>
【译】SQL Server误区30日谈-Day12-TempDB的文件数和需要和CPU数目保持一致
查看>>
不为技术而技术:大型网站架构演化解析
查看>>
Java文件清单列表
查看>>
js url传值中文乱码之解决之道
查看>>
Atitit.获取某个服务 网络邻居列表 解决方案
查看>>
Trusty TEE
查看>>
[LeetCode] Reverse String 翻转字符串
查看>>
学习iOS【3】数组、词典和集合
查看>>
Hessian 原理分析--转
查看>>
转: 基于netty+ protobuf +spring + hibernate + jgroups开发的游戏服务端
查看>>
easyui传入map的数据前台展示出tree格式数据
查看>>
悲观的思考,乐观的生活.我们既需要思考的深度,也需要生活的温度!
查看>>
java.math.BigDecimal
查看>>
Vitamio中文API文档(4)—— VitamioInstaller
查看>>
河内之塔
查看>>
图像处理之基础---内窥镜医学图像增强
查看>>