Builder Design Pattern in Swift


Greetings, traveler!

Let’s continue our fascinating journey into the world of Design Patterns. Today, we unveil the next Creational Design Pattern, the Builder. This technique allows you to construct complex objects piece by piece. Intrigued? Let’s delve deeper.

Example of usage

Let’s take a closer look at a live example. Imagine that we need to build a piece of furniture. It can be a table, chair, or sofa made with different kinds of wood and various colors. We need a guy to handle all these details to create such an object. This guy needs specific commands to build the desired object. So, let’s do that!

First, let’s create entities to determine the characteristics of our furniture. 

enum FurnitureKind {
    case chair, table, sofa
}

enum WoodKind {
    case oak, pine, cherry
}

Next, create a model for our furniture. 

struct Furniture {
    let kind: FurnitureKind
    let color: UIColor
    let material: WoodKind
}

Last but not least, let’s create our Builder. In this Builder, we will add properties to construct our Furniture model. These properties can include the type of furniture, the material used, and the color. After that, we can create functions to set a desired value to these properties. These functions can return a value of our Builder — we can add this functionality for more convenient calls. But if we don’t want to use these functions like this every time, we can mark them with the @discardableResult attribute. The last function will return the Furniture model.  

final class FurnitureBuilder {
    
    private var kind: FurnitureKind = .chair
    private var color: UIColor = .brown
    private var material: WoodKind = .cherry
    
    @discardableResult
    func with(kind: FurnitureKind) -> FurnitureBuilder {
        self.kind = kind
        return self
    }
    
    @discardableResult
    func with(color: UIColor) -> FurnitureBuilder {
        self.color = color
        return self
    }
    
    @discardableResult
    func with(material: WoodKind) -> FurnitureBuilder {
        self.material = material
        return self
    }
    
    func build() -> Furniture {
        Furniture(
            kind: kind,
            color: color,
            material: material
        )
    }
    
}

Now, we can use it:

let furniture = FurnitureBuilder()
    .with(kind: .table)
    .with(color: .purple)
    .with(material: .pine)
    .build()

Conclusion

We are done with the Builder Pattern. It’s pretty easy to understand and offers a convenient approach. The benefits of using this pattern include improved code readability, flexibility in object creation, and the ability to construct complex objects step by step. That’s my take on it. And what do you think? 

In the following article, we will discuss a Prototype pattern. See you there!