Design patterns are named, reusable solutions to common design problems. Their names make tradeoffs easier to discuss, but recognizing a pattern is only the beginning. Each article below develops its contracts, implementation, failure paths, and testing strategy in Swift.
Many classic patterns come from the 1994 “Gang of Four” book, Design Patterns. Some are built right into Swift and Apple’s frameworks (delegation, observers, singletons), while others need a Swift-flavored twist with protocols, closures, and value types.
The dedicated examples use a Swift 5.7 baseline, released on September 12, 2022. The coordinator example requires iOS 16 or macOS 13 for NavigationStack. Related articles on delegation, observers, iteration, strategy, and dependency injection state their own language context.
Read the examples in order within each article: later Swift blocks extend the earlier definitions and include executable assertions. Diagrams show ownership, dispatch, and state transitions; equations appear where resource accounting or representation cost benefits from a precise model.
Article available Coming soon
1. Creational Patterns
How objects get created:
Singleton in Swift: Shared Identity, Initialization, and Hidden Dependencies
A singleton gives a service one shared identity and a globally reachable access point. Those are two separate decisions: an application may...
Factory Method in Swift: A Stable Workflow with a Construction Hook
Factory Method lets a stable algorithm ask an overridable creation operation for the product it will use. The algorithm controls the workflow;...
Abstract Factory in Swift: Construct Compatible Families of Capabilities
Abstract Factory creates related products that belong to one compatible family. A theme might supply labels and buttons, while another theme supplies...
Builder in Swift: Assemble Configuration Without Publishing Invalid State
A builder separates assembling configuration from publishing a usable product. It is helpful when construction has several optional choices and cross-field validation...
Prototype in Swift: Copying Values, Cloning Objects, and Preserving Identity Rules
Prototype creates a new object from an existing example rather than assembling every field from scratch. The difficult part is defining what...
Object Pools in Swift: Bounded Resources, Leases, and Reliable Return
An object pool reuses a bounded set of resources instead of constructing a fresh resource for every operation. It is useful when...
Lazy Initialization in Swift: Deferred Work, Failure, and Concurrency
Lazy initialization defers work until its result is needed. That can avoid expensive startup work, but it moves cost, failure, and resource...
Monostate in Swift: Separate Instances with One Shared State
Monostate allows several object instances while their operations all use one shared state. It differs from Singleton’s one shared object identity: two...
2. Structural Patterns
How objects are composed into bigger structures:
Adapter in Swift: Translate Contracts Without Hiding Meaning
An adapter translates one contract into another so an existing capability can participate in a new system. The translation can involve units,...
Bridge in Swift: Separate Two Independent Axes of Variation
Bridge separates a high-level abstraction from the implementation capability it uses, so both can vary independently. A notification’s presentation policy and its...
Composite in Swift: Treat Leaves and Groups Through One Honest Contract
Composite lets a client work uniformly with individual elements and groups of elements. A document outline is a natural fit: an item...
Decorator in Swift: Add Behavior While Preserving the Capability Contract
Decorator adds behavior around an existing capability while presenting the same interface. A reader can be counted, cached, or traced without making...
Facade in Swift: Give a Use Case One Coherent Entry Point
A facade gives a caller one coherent entry point to a subsystem’s use case. It can validate input, coordinate storage, and update...
Flyweight in Swift: Share Immutable Intrinsic State Without Sharing Edits
Flyweight shares immutable intrinsic state across many small objects while keeping context-specific state separate. A text layout can share style resources across...
Proxy in Swift: Control Access, Loading, and Cache Validity
A proxy presents a subject’s interface while controlling access to that subject. It may defer construction, check permission, or reuse a cached...
3. Behavioral Patterns
How objects communicate and share responsibilities:
Delegation in Swift: One Object Reporting to Another
A picker knows which item the user selected. The screen that owns the picker knows what that selection means for the application....
The Observer Pattern in Swift: Subscriptions, Ordering, and Cancellation
An observer API is a delivery contract, not merely an array of closures. Callers need to know who retains a subscription, whether...
Publisher-Subscriber in Swift: Typed Events, Queued Delivery, and Subscription Lifetime
Publisher-subscriber separates event producers from independently subscribed consumers. A typed event bus can be a useful local implementation, but delivery timing, reentrancy,...
Chain of Responsibility in Swift: Explicit Handling, Rejection, and Fallthrough
Chain of Responsibility passes a request through ordered handlers until one takes responsibility. Each handler must distinguish “not mine” from “handled and...
Command in Swift: Model Actions, Undo, and Redo as Explicit Operations
Command represents an action as a value or object that can be passed, recorded, queued, or executed by another owner. For local...
Iterators and Sequences in Swift: Pull Values Without Assuming Replay
A for loop asks an iterator for the next element until the iterator says it has finished. The sequence supplying that iterator...
Mediator in Swift: Coordinate Colleagues Without a Web of Callbacks
Mediator centralizes interaction rules among collaborating components. A delivery form’s mode selector, address field, and pickup field should not each call every...
Memento in Swift: Restore Owned State Through Opaque Snapshots
Memento captures a receiver’s state so another object can request restoration without interpreting that state. A history caretaker stores opaque snapshots; the...
State in Swift: Make Transitions and Legal Operations Explicit
State makes an object’s legal behavior depend on an explicit current phase. A transfer can be running, paused, completed, or failed; independent...
Composition Over Inheritance in Swift
A class hierarchy is tempting when two features share behavior. But “uses the same behavior” is weaker than “is a valid kind...
Template Method in Swift: Fix the Algorithm and Expose Narrow Hooks
Template Method fixes an algorithm’s overall sequence while allowing subclasses to vary selected steps. It is useful when a base type intentionally...
Visitor in Swift: Double Dispatch, New Operations, and the Closed Node Set
Visitor adds operations over a known family of element types without putting every operation into those element types. A document can support...
Null Object in Swift: An Explicit No-Op Policy Instead of Missing Behavior
Null Object supplies a deliberate neutral implementation of a capability. A feature can call optional diagnostics without checking an optional logger at...
Specification in Swift: Compose Rules with Clear Evaluation Semantics
Specification represents a rule that can be evaluated against a candidate and composed with other rules. A catalog filter such as “available...
4. App-Level Patterns
Patterns that shape how a whole app or feature is organized:
Coordinator in Swift: Navigation, Child Flows, and Ownership
A coordinator owns navigation decisions and the lifetime of child flows. Screens report user intent; the coordinator decides which route follows and...
Repository in Swift: Domain Contracts, Cache Policy, and Consistent Writes
A repository exposes a domain-facing way to obtain and update entities while hiding persistence-specific details. It should define freshness, conflict, and failure...
Dependency Injection in Swift Without a Container
A feature is difficult to test when it secretly reads the clock, opens a database, or creates its own network client. Dependency...
Service Locators and Registries in Swift: Resolution, Scope, and Hidden Dependencies
A registry records how capabilities are constructed. A service locator lets code discover those capabilities at runtime. The same container can be...
Front Controller in Swift: Validate and Dispatch Incoming Requests in One Place
A front controller is a common entry point for incoming requests. It validates routing input, applies shared access policy, dispatches one use...
Three-Tier Architecture in Swift: Presentation, Use Cases, and Data Boundaries
Three-tier architecture separates presentation, application behavior, and data management. Those responsibilities can be deployed as client, application server, and database, while their...
Looking for MVC, MVVM, and friends? They have a guide of their own: see Architectures.
Up next
Architectures