The abstract factory pattern is used to provide a client with a set of related or dependant objects. The “family” of objects created by the factory are determined at run-time.

Example:


_Protocols:_
protocol CoffeeDescribe {
    var ingredients: [String] { get }
}

struct Coffee: CoffeeDescribe {
    let ingredients: [String]
}

protocol CoffeeMaking {
    func  make() -> CoffeeDescribe
}

Implementation:

final class IcedInstantCoffee: CoffeeMaking {
    func make() -> CoffeeDescribe {
        return Coffee(ingredients: ["Water", "Ice", "coffee", "creame"])
    }
}

final class Espresso: CoffeeMaking {
    func make() -> CoffeeDescribe {
        return Coffee(ingredients: ["coffee", "milk", "water", "sugar", "cinnamon"])
    }
}

Abstract factory

enum CoffeeFactoryType: CoffeeMaking {
    case icedCoffee
    case espresso

    func make() -> CoffeeDescribe {
        switch self {
        case .icedCoffee:
            return IcedInstantCoffee().make()
        case .espresso:
            return Espresso().make()
        }
    }
}

Usage:

let icedCoffee = CoffeeFactoryType.icedCoffee.make()
let espresso = CoffeeFactoryType.espresso.make()

print(icedCoffee.ingredients)
print(espresso.ingredients)