Factory Method Design Pattern in Swift

1. Definition

The Factory Method is a creational design pattern that provides an interface for creating objects, but allows subclasses to alter the type of objects that will be created.

2. Problem Statement

Imagine you're developing a UI library, and you want to allow users to create custom buttons without altering existing code. If you hard-code the button types, adding a new button style would require changes to the entire library, breaking the Open/Closed principle.

3. Solution

The Factory Method pattern suggests that you replace direct object construction calls (using the new operator) with calls to a special factory method. Objects returned by a factory method are often referred to as "products."

4. Real-World Use Cases

1. A UI library where developers can introduce new styles of buttons without recompiling the library.

2. An e-commerce platform allowing vendors to provide their custom payment gateways.

5. Implementation Steps

1. Declare a creator interface with the factory method.

2. Concrete creators will implement the factory method and return different types of products.

3. Declare a product interface.

4. Concrete products implement the product interface.

6. Implementation in Swift Programming

// Step 3: Declare a product interface.
protocol Button {
    func render()
}
// Step 4: Concrete products implement the product interface.
class WindowsButton: Button {
    func render() {
        print("Rendering a Windows-style button.")
    }
}
class MacButton: Button {
    func render() {
        print("Rendering a Mac-style button.")
    }
}
// Step 1: Declare a creator interface with the factory method.
protocol Dialog {
    func createButton() -> Button
}
// Step 2: Concrete creators implement the factory method.
class WindowsDialog: Dialog {
    func createButton() -> Button {
        return WindowsButton()
    }
}
class MacDialog: Dialog {
    func createButton() -> Button {
        return MacButton()
    }
}
// Usage
func displayDialog(for dialog: Dialog) {
    let button = dialog.createButton()
    button.render()
}
let windowsDialog = WindowsDialog()
let macDialog = MacDialog()
displayDialog(for: windowsDialog)
displayDialog(for: macDialog)

Output:

Rendering a Windows-style button.
Rendering a Mac-style button.

Explanation:

1. We've created a Button protocol which is our product interface. WindowsButton and MacButton are concrete products.

2. The Dialog protocol is our creator interface with a factory method createButton().

3. WindowsDialog and MacDialog are concrete creators. They implement the factory method and produce a product (Button).

4. In usage, based on the type of Dialog passed to displayDialog, the appropriate button is rendered.

7. When to use?

The Factory Method pattern can be used when:

1. The exact type of the product isn't known until runtime.

2. The creation process is complex or involves multiple steps.

3. The product needs to be extended to subclasses.

4. The creator class should remain decoupled from its products.


Comments