Builder Pattern iOS Swift

Luan Ho Si
Mac O’Clock
Published in
3 min readMay 18, 2020

What is the Builder Pattern?

Builder Pattern is a Design Pattern that allows you to create a complex object step by step, instead of input all required parameters via initializer.

If your object has a lot of properties and they can be provided in any order, you could use the builder pattern to reduce the complexity of the initialization by providing properties step by step.

Builder Pattern has three main part:

Source: Design Patterns by Tutorials (raywenderlich.com)
  • Product: is the object that will be generated by this Pattern
  • Director: receive inputs and work with Builder to create Product. On the other hand, the Director uses Builder to create Product
  • Builder: define all steps to create a Product and handle the creation of Product with build function, which is called after all of other steps.

This pattern works best for creating a complex object with multiple steps. But if you don’t need to do everything step by step or you don’t have several parameters to input, maybe Builder Pattern is not a good choice for you.

Example

You could use Builder Pattern to create a glass of Milk Tea. The Product is MilkTea Model, which has a type, size and toppings properties. The Director could be a Bartender, who knows how to make a glass of Milk Tea from customer requirements.

Firstly, You need to define a MilkTea Product, which has properties type, size, and toppings.

// Product
public struct MilkTea {
public let type: MilkTeaType
public let size: Size
public let toppings: Topping
}

Define Milk Tea Builder to create a Milk Tea Model step by step, don’t forget to check for sold out an ingredient.

public class MilkTeaBuilder {
public private(set) var type: MilkTeaType = .Classic
public private(set) var size: Size = .Medium
public private(set) var toppings: Topping = []
private var soldOutTypes: [MilkTeaType] = []
// check available milk tea type
private func isTypeAvailable(value: MilkTeaType) -> Bool {
if soldOutTypes.contains(value) {
return false
}
return true
}
public func setType(value: MilkTeaType) throws {
guard isTypeAvailable(value: value) else {
throw Error.SoldOutType
}
self.type = value
}

public func setSize(value: Size) {
self.size = value
}
public func addToppings(value: Topping) {
self.toppings.insert(value)
}
public func removeTopping(value: Topping) {
self.toppings.remove(value)
}
func build() -> MilkTea {
return MilkTea(type: type, size: size, toppings: toppings)
}
}

This is the Director, Bartender is the one who use Milk Tea Builder to create a glass of Milk Tea

public class Bartender {
func createClassicMilkTea() throws -> MilkTea {
let builder = MilkTeaBuilder()
try builder.setType(value: .Classic)
builder.setSize(value: .Medium)
builder.addToppings(value: [.AloeJelly, .LycheeJelly])
return builder.build()
}
func createMatchaMilkTea() throws -> MilkTea {
let builder = MilkTeaBuilder()
try builder.setType(value: .Matcha)
builder.setSize(value: .Medium)
builder.addToppings(value: [.coconutJelly])
return builder.build()
}
}

This is actually how everything will work

// MARK: - Main functionlet Christopher = Bartender()do {
let classicMilkTea = try Christopher.createClassicMilkTea()
print(classicMilkTea.description)
} catch Error.SoldOutType {
print("Not enough milktea type")
} catch let error {
print("An Error occurs: \(error)")
}

Complete Source code: https://github.com/LuanSiHo/Design-Pattern.git

This article is the result of reading Builder Pattern Chapter in Design Pattern by Tutorial (by the raywenderlich Tutorial Team). You guys could read that book to learn more about Design Pattern in Swift

--

--