Prototype Design Pattern in Swift


Greetings, traveler!

We continue our exploration of Creational Design Patterns. Now, it is the turn of the Prototype Design Pattern.

When might we need to use it? Consider a scenario where we need to create multiple copies of an object, each with minor differences. How could we approach this? Sure thing, we can create something like this.

struct Object {
    var name: String
    var color: UIColor
    var count: Int
}

let firstObject = Object(name: "First Name", color: .red, count: 1)
let secondObject = Object(name: "Second Name", color: .red, count: 1)
let thirdObject = Object(name: "Third Name", color: .red, count: 1)

But it looks inconvenient. We can also make a mistake while copying the code. However, we can follow the Prototype pattern, which will simplify the process and reduce the chances of errors. 

Example of usage

Let’s take a real-world example to illustrate the Prototype Design Pattern. Imagine we’re designing a furniture catalog. We need to create a set of furniture: chair, table, and sofa. We created a model for these objects in our previous discussion on the Builder pattern. Let’s repeat the code.

enum FurnitureKind {
    case chair, table, sofa
}

enum WoodKind {
    case oak, pine, cherry
}

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

Now, let’s create multiple copies of it. Every single copy will have only one difference — the furniture type. 

let chair = Furniture(kind: .chair, color: .brown, material: .cherry)
let table = Furniture(kind: .table, color: .brown, material: .cherry)
let sofa = Furniture(kind: .sofa, color: .brown, material: .cherry)

Let’s create a function inside our Furniture model to avoid mistakes and achieve a cleaner solution.

struct Furniture {
    
    let kind: FurnitureKind
    let color: UIColor
    let material: WoodKind
    
    func copy(
        kind: FurnitureKind? = nil,
        color: UIColor? = nil,
        material: WoodKind? = nil
    ) -> Furniture {
        
        Furniture(
            kind: kind ?? self.kind,
            color: color ?? self.color,
            material: material ?? self.material
        )
    }
    
}

And now, let’s use it:

let chair = Furniture(kind: .chair, color: .brown, material: .cherry)
let table = chair.copy(kind: .table)
let sofa = chair.copy(kind: .sofa)

Much better!

Conclusion

This is all I wanted to say about the Prototype Design Pattern. In the following article, we will talk about Singleton (finally!) — see you there!