Software Design

Swift Factory Method Pattern: Why Use It Instead of init

Swift factory functions give creation logic intent-revealing names and make return types and reuse policies flexible. This covers when to choose static func over init and how it differs from the GoF Factory Method.

4 min read
Cover image for Swift Factory Method Pattern: Why Use It Instead of init

When building apps with Swift, you end up writing object-creation code dozens of times a day.

At some point, though, using just init starts to feel limiting.

Many developers begin with init everywhere, then discover the Factory Method pattern as the project grows.

This article explains Swift’s Factory Method pattern and why you might use a factory instead of init, with practical code examples.

The Factory Method Pattern in One Sentence

Let’s start with the key answer.

A factory method moves object-creation logic into a separate method outside init, gives it a meaningful name, and lets you choose the return type freely.

In Swift, this usually refers to a static factory method created with static func.

Here, we mean a static factory that wraps creation in a type method. It differs from the GoF pattern, where a subclass determines the concrete type; we compare the boundary between them in Factory Method vs. Abstract Factory.

init operates within rules defined by the language.

You cannot give it a custom name, and it must always create a new instance of its own type.

Factory methods remove these constraints.

Here’s a simple example.

struct Color {
    let r, g, b: Double
    // Make the creation intent clear in the name
    static func rgb(_ r: Double, _ g: Double, _ b: Double) -> Color {
        Color(r: r, g: g, b: b)
    }
    static func gray(_ v: Double) -> Color {
        Color(r: v, g: v, b: v)
    }
}

When called like Color.gray(0.5), the code alone tells you that it creates gray.


Why Use a Factory Instead of init?

Based on my experience, there are four main reasons.

First, you can name it.

All init methods have the same name, so you must distinguish them only by their parameters.

Multiple initializers taking two Double values can quickly become confusing.

Factory methods put intent into names such as from(hex:) and rgb(_:_:_:).

Second, you do not need to create a new instance every time.

init always returns a new object, whereas a factory can return a cached value or a singleton.

Third, you can choose the return type flexibly.

Depending on the situation, it can return a subtype or a different implementation.

Fourth, failure handling can be expressed more clearly.

Adding one static func line makes the code much easier to read
Adding one static func line makes the code much easier to read

Below is an example of a factory that uses caching.

final class IconCache {
    private static var store: [String: Icon] = [:]
    // Reuse an icon that has already been created for the same name
    static func icon(named name: String) -> Icon {
        if let cached = store[name] { return cached }
        let icon = Icon(name: name)
        store[name] = icon
        return icon
    }
}

When the same icon is requested repeatedly, you can save memory.

Return it if present; otherwise create it and cache it
Return it if present; otherwise create it and cache it

So, Do You No Longer Need init?

No, absolutely not.

A factory does not replace init; it is a tool that wraps it.

Even inside a factory method, you ultimately call init to create the object.

For a simple value type or obvious creation logic, plain init is better.

Wrapping it in a factory for no reason only makes the code longer and harder to read.

Factories shine in specific situations.

  • When there are multiple creation methods and you want to distinguish them by name
  • When reuse is needed through caching or pooling
  • When you want to hide a complex initialization process in one place
  • When you want to hide the implementation by returning a protocol type

If none of these apply, use init.

The Swift standard library makes this distinction too.

Array(repeating:count:) is an init, while static properties such as UIColor.systemBlue are effectively factory cousins.


Practical Decision Criteria

Here’s the rule of thumb I use when I’m unsure, summarized in a table.

Situation Recommendation
Storing simple values init
Multiple creation methods Factory method
Instance reuse or caching Factory method
Hide implementation and return a protocol Factory method
Initialization takes one line init
I recall this table whenever I'm unsure which one to choose
I recall this table whenever I'm unsure which one to choose

In short, init handles “how to create,” while a factory handles “what to create and why.”

They are not competitors; they are partners with different roles.

I recommend starting with init and moving to a factory when the creation logic becomes complex.

Remembering these criteria will make your code cleaner. Happy Swift coding!