美文网首页
读《Design-Patterns-by-Tutorials》笔

读《Design-Patterns-by-Tutorials》笔

作者: Beyond_JG | 来源:发表于2018-10-09 15:57 被阅读93次

构造器模式允许一步一步的创建一个复杂的对象而不是一次创建完成。这个模式包括三个主要类型,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: - Product
public 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: - Builder
public 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: - Director
public 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: - Example
let 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 burger
Sorry, no kitten burgers here... :[

What should you be careful about?

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

Tutorial project

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

示例项目
Demo

预告

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

相关文章

  • 读《Design-Patterns-by-Tutorials》笔

    单例模式限制一个类仅仅有一个实例。每个这个类的引用都指向同一个实例。在 iOS 开发中非常常见这种模式,因为 Ap...

  • 读《Design-Patterns-by-Tutorials》笔

    备忘录模式允许一个对象可以被保存和恢复。包括三个部分。 Originator: 需要被保存和恢复的对象。 Meme...

  • 读《Design-Patterns-by-Tutorials》笔

    观察者模式让一个对象观察另一个对象的改变。在本章节,你将学习两种实现观察者模式的方法: 使用 KVO 使用一个Ob...

  • 读《Design-Patterns-by-Tutorials》笔

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

  • 笔读

    笔读是什么? 笔读就是在读书时,在书上画记号,写记号,写感想,书评文章等方式。 为什么要做笔读呢? 做笔读可以帮自...

  • 关于英语学习和点读笔的使用

    对于口语不好的父母,可以选择点读笔搭配使用。但是不是用了点读笔,父母就把孩子完完全全的交给点读笔了。哪怕用了点读笔...

  • 说下市场上利用率比较高的几款开放式点读笔,可以点读普通书的点读笔

    为什么要说点读笔的利用率比较高呢?因为市场上分2种点读笔类型,一种为封闭式点读笔,一种为开放式点读笔。 封闭式的笔...

  • 点读笔的乐趣

    昨晚和儿子一起玩了会儿点读笔,说起我家这根点读笔,真有种买完笔配不起书的赶脚。 关键是和毛毛虫点读笔配套的点读...

  • 爱贝亲子点读笔产品分析

    爱贝亲子点读笔是一款开放式点读笔,爱贝亲子点读笔凭借着点读笔、点读卡、客户端和网络平台的四维运营模式,让所有的普通...

  • 读笔

    刚开始读《余光中散文精选》时,感觉很无聊,尤其是有些字生僻难懂,都不会读且不认识。第一节的时候有点读不进去,但是当...

网友评论

      本文标题:读《Design-Patterns-by-Tutorials》笔

      本文链接:https://www.haomeiwen.com/subject/ysfyaftx.html