TechBlogs

๐Ÿƒโ€โ™€๏ธBehavioral Design Pattern

โ›“๏ธ Chain Of Responsibility(Behavioral)

Decouples request senders from receivers by allowing multiple handlers to process a request sequentially. Each handler decides to act or pass it down the chain.

Example - Expense Approval System A Swift implementation of the Chain of Responsibility behavioral design pattern for handling multi-level expense approvals in a corporate workflow. Define Expenses -> Build the Chain -> Submit for Approval Features

// MARK: - Expense Report Model
/// Represents an expense request submitted for approval.
struct ExpenseReport {
    let id: UUID
    let amount: Double
    let description: String
    let category: String // e.g., "Travel", "Equipment"
}

// MARK: - Handler Protocol
/// Defines the interface for all approval handlers in the chain.
protocol ExpenseApprover: AnyObject {
    var nextApprover: ExpenseApprover? { get set }
    func approve(_ expense: ExpenseReport) -> String
}

// MARK: - Concrete Handlers

/// Manager can approve expenses up to $1,000.
final class Manager: ExpenseApprover {
    var nextApprover: ExpenseApprover?
    private let approvalLimit: Double = 1_000
    
    func approve(_ expense: ExpenseReport) -> String {
        if expense.amount <= approvalLimit {
            return "โœ… Manager approved expense #\(expense.id) (\(expense.description))"
        } else {
            return nextApprover?.approve(expense) ?? "โŒ Rejected: No higher authority!"
        }
    }
}

/// Director can approve expenses up to $5,000.
final class Director: ExpenseApprover {
    var nextApprover: ExpenseApprover?
    private let approvalLimit: Double = 5_000
    
    func approve(_ expense: ExpenseReport) -> String {
        if expense.amount <= approvalLimit {
            return "โœ… Director approved expense #\(expense.id) (\(expense.description))"
        } else {
            return nextApprover?.approve(expense) ?? "โŒ Rejected: Requires CFO review!"
        }
    }
}

/// CFO is the final authority with special rules for travel expenses.
final class CFO: ExpenseApprover {
    var nextApprover: ExpenseApprover? = nil
    
    func approve(_ expense: ExpenseReport) -> String {
        if expense.category == "Travel" && expense.amount > 10_000 {
            return "โŒ Rejected: Travel expenses cannot exceed $10,000"
        } else {
            return "โœ… CFO approved expense #\(expense.id)"
        }
    }
}

// MARK: - Chain Setup & Demo
func buildApprovalChain() -> ExpenseApprover {
    let manager = Manager()
    let director = Director()
    let cfo = CFO()
    
    manager.nextApprover = director
    director.nextApprover = cfo
    
    return manager
}

// Example Usage
let chain = buildApprovalChain()

let expenses = [
    ExpenseReport(id: UUID(), amount: 800, description: "Team lunch", category: "Food"),
    ExpenseReport(id: UUID(), amount: 4_500, description: "Conference tickets", category: "Travel"),
    ExpenseReport(id: UUID(), amount: 12_000, description: "Business class flight", category: "Travel")
]

for expense in expenses {
    print(chain.approve(expense))
}

/* Output:
โœ… Manager approved expense #... (Team lunch)
โœ… Director approved expense #... (Conference tickets)
โŒ Rejected: Travel expenses cannot exceed $10,000
*/

๐Ÿ–ฅ๏ธ Command (Behavioral)

Example Scenario: A food delivery app (like Uber Eats) needs to handle orders, undo operations (cancel items), queue requests, and remote kitchen workflows. The Command Pattern encapsulates each order as an object, making it easy to execute, queue, or undo operations. Swift Implementation: Restaurant Order System

(Single-file, scalable, with clear comments)

  1. Key Components

    Command Protocol: Defines execute() and undo().

    Concrete Commands: Encapsulate actions like AddToCartCommand, CancelOrderCommand.

    Invoker (OrderManager): Manages command execution, history (for undo), and queuing.

    Receiver (KitchenSystem): Actually performs the actions (e.g., cooks food).

import Foundation

// MARK: - ๐Ÿฝ๏ธ Receiver
// The Receiver is the object that knows how to perform the actual work.
// It contains the business logic for the actions requested by the commands.
final class KitchenSystem {
    private var preparedDishes: [String] = []

    func prepareOrder(_ dish: String) {
        preparedDishes.append(dish)
        print("๐Ÿง‘โ€๐Ÿณ Cooking: \(dish).")
    }

    func cancelOrder(_ dish: String) {
        if let index = preparedDishes.firstIndex(of: dish) {
            preparedDishes.remove(at: index)
            print("๐Ÿšซ Cancelled: \(dish).")
        } else {
            print("โŒ Error: \(dish) was not in the prepared list.")
        }
    }
}

// MARK: - ๐Ÿ“œ Command Protocol
// This protocol defines the common interface for all commands.
// It requires an `execute` method to perform an action and an `undo` method to reverse it.
protocol Command {
    func execute()
    func undo()
}

// MARK: - โž• AddToCartCommand
// This concrete command encapsulates the request to add an item to the cart.
// It holds a reference to the Receiver (`KitchenSystem`) and the necessary parameters (`dish`).
final class AddToCartCommand: Command {
    private let kitchen: KitchenSystem
    private let dish: String

    init(kitchen: KitchenSystem, dish: String) {
        self.kitchen = kitchen
        self.dish = dish
    }

    func execute() {
        print("โžก๏ธ Executing AddToCartCommand.")
        kitchen.prepareOrder(dish)
    }

    func undo() {
        print("โฌ…๏ธ Undoing AddToCartCommand.")
        kitchen.cancelOrder(dish)
    }
}

// MARK: - โŒ CancelOrderCommand
// This concrete command encapsulates the request to cancel an order.
final class CancelOrderCommand: Command {
    private let kitchen: KitchenSystem
    private let dish: String

    init(kitchen: KitchenSystem, dish: String) {
        self.kitchen = kitchen
        self.dish = dish
    }

    func execute() {
        print("โžก๏ธ Executing CancelOrderCommand.")
        kitchen.cancelOrder(dish)
    }

    func undo() {
        // Undoing a cancellation is complex and context-dependent.
        // In this simple example, we'll log a message. In a real app,
        // this might involve creating a new 'prepare' command.
        print("โฌ…๏ธ Undoing CancelOrderCommand is not supported in this implementation.")
    }
}

// MARK: - ๐Ÿ—ƒ๏ธ Invoker
// The Invoker holds and manages the commands. It doesn't know about the
// details of the commands or the Receiver. Its job is to execute and manage
// a history of commands, enabling features like undo/redo.
final class CommandInvoker {
    private var history = [Command]()

    func executeCommand(_ command: Command) {
        command.execute()
        history.append(command)
    }

    func undoLastCommand() {
        guard !history.isEmpty else {
            print("โš ๏ธ No commands to undo.")
            return
        }
        let lastCommand = history.removeLast()
        lastCommand.undo()
    }
}

// MARK: - ๐Ÿš€ Usage
// The client code creates the commands and hands them off to the Invoker.
// It interacts with the Invoker, not the commands or the Receiver directly,
// demonstrating a clean separation of concerns.

let kitchen = KitchenSystem()
let invoker = CommandInvoker()

// User adds items to the cart, the invoker executes the commands
invoker.executeCommand(AddToCartCommand(kitchen: kitchen, dish: "Burger"))
invoker.executeCommand(AddToCartCommand(kitchen: kitchen, dish: "Pizza"))

// User decides to undo the last action
print("\nUser decides to undo the last action...\n")
invoker.undoLastCommand()

// User undoes another action
print("\nUser decides to undo another action...\n")
invoker.undoLastCommand()

๐Ÿ“œ Interpreter (Behavioral)

This oneโ€™s a bit rarer in day-to-day iOS code, but itโ€™s perfect for situations where you need to define a grammar and evaluate sentences in that grammar โ€” like a mini language, filter system, or search query parser

Example: Simple Math Expression Interpreter

Weโ€™ll make a very small interpreter that can evaluate expressions like:

"5 + 3 - 2" โ†’ 6

import Foundation

// MARK: - Expression Protocol
protocol Expression {
    func interpret() -> Int
}

// MARK: - Terminal Expression
struct NumberExpression: Expression {
    private let number: Int
    init(_ number: Int) {
        self.number = number
    }
    func interpret() -> Int {
        return number
    }
}

// MARK: - Non-Terminal Expressions
struct AddExpression: Expression {
    private let left: Expression
    private let right: Expression
    
    init(_ left: Expression, _ right: Expression) {
        self.left = left
        self.right = right
    }
    
    func interpret() -> Int {
        return left.interpret() + right.interpret()
    }
}

struct SubtractExpression: Expression {
    private let left: Expression
    private let right: Expression
    
    init(_ left: Expression, _ right: Expression) {
        self.left = left
        self.right = right
    }
    
    func interpret() -> Int {
        return left.interpret() - right.interpret()
    }
}

// MARK: - Client Code: Parsing a simple space-separated expression
func parseExpression(_ input: String) -> Expression {
    let tokens = input.split(separator: " ").map { String($0) }
    
    var currentExpression: Expression = NumberExpression(Int(tokens[0])!)
    
    var index = 1
    while index < tokens.count {
        let op = tokens[index]
        let number = NumberExpression(Int(tokens[index + 1])!)
        
        if op == "+" {
            currentExpression = AddExpression(currentExpression, number)
        } else if op == "-" {
            currentExpression = SubtractExpression(currentExpression, number)
        }
        
        index += 2
    }
    return currentExpression
}

// MARK: - Usage
let expression = parseExpression("5 + 3 - 2")
print("Result: \(expression.interpret())") // Result: 6

๐Ÿ’ก Why This Is Interpreter


iOS Real-World Analogy

๐Ÿ” Iterator(Behavioral)

The Iterator is a behavioral design pattern that provides a way to access elements of a collection sequentially without exposing its underlying representation. Itโ€™s one of the most fundamental and frequently used patterns in iOS development. Core Concept

Problem: You need to traverse different collections (arrays, trees, graphs) in a standardized way without coupling your code to their specific implementations.

Solution: The Iterator pattern:

struct FoodItem: CustomStringConvertible {
    let name: String
    let isVegetarian: Bool
    let price: Double
    
    var description: String {
        return name
    }
}

// ---------------------------------------------------------------------------------------------------------------------

struct Menu {
    private let items: [FoodItem]
    
    init(items: [FoodItem]) {
        self.items = items
    }
}

extension Menu: Sequence {
    // The makeIterator() method needs to return an iterator
    // that knows how to filter for vegetarian items.
    func makeIterator() -> VegetarianIterator {
        return VegetarianIterator(items: self.items)
    }
}

struct VegetarianIterator: IteratorProtocol {
    private var internalIterator: IndexingIterator<[FoodItem]>

    init(items: [FoodItem]) {
        self.internalIterator = items.makeIterator()
    }
    
    mutating func next() -> FoodItem? {
        while let item = internalIterator.next() {
            if item.isVegetarian {
                return item
            }
        }
        return nil
    }
}

// ---------------------------------------------------------------------------------------------------------------------

// Usage:
let menu = Menu(items: [
    FoodItem(name: "Pizza", isVegetarian: true, price: 12.99),
    FoodItem(name: "Steak", isVegetarian: false, price: 24.99),
    FoodItem(name: "Salad", isVegetarian: true, price: 8.99)
])

print("Vegetarian options:")
for item in menu {
    print("- \(item.name) at $\(item.price)")
}
// Prints
//Vegetarian options:
//- Pizza at $12.99
//- Salad at $8.99

Real-World iOS Examples

 // Core Data NSFetchedResultsController:
let controller: NSFetchedResultsController<FoodItem> = ...
for item in controller.fetchedObjects ?? [] {
    // Iterates through managed objects
}

// File System Enumeration:
let files = FileManager.default.enumerator(atPath: "/path")
while let file = files?.nextObject() as? String {
    print(file)
}

// Combine Publishers:
[1, 2, 3]
    .publisher
    .sink { value in
        print(value) // Implicit iterator
    }

Key Benefits in iOS Development

๐Ÿ“ก Mediator (Behavioral):

The Mediator pattern centralizes complex communication between related objects, making them communicate through a single mediator instead of directly. This reduces tight coupling and simplifies maintenance, especially useful in UI frameworks like chat apps or Stock trading app

Example:

// Mediator Protocol
protocol AirTrafficControl {
    func register(aircraft: Aircraft)
    func send(message: String, from sender: Aircraft)
}

// Concrete Mediator
class ControlTower: AirTrafficControl {
    private var aircrafts: [Aircraft] = []
    
    func register(aircraft: Aircraft) {
        aircrafts.append(aircraft)
        aircraft.controlTower = self
    }
    
    func send(message: String, from sender: Aircraft) {
        for aircraft in aircrafts {
            // Don't send the message back to the sender
            if aircraft !== sender {
                aircraft.receive(message: message)
            }
        }
    }
}

// Colleague Protocol
protocol Aircraft: AnyObject {
    var name: String { get }
    var controlTower: AirTrafficControl? { get set }
    func send(message: String)
    func receive(message: String)
}

// Concrete Colleagues
class Airplane: Aircraft {
    let name: String
    weak var controlTower: AirTrafficControl?
    
    init(name: String) {
        self.name = name
    }
    
    func send(message: String) {
        print("\(name) sends: \(message)")
        controlTower?.send(message: message, from: self)
    }
    
    func receive(message: String) {
        print("\(name) receives: \(message)")
    }
}

// Usage
let tower = ControlTower()

let boeing747 = Airplane(name: "Boeing 747")
let airbusA380 = Airplane(name: "Airbus A380")
let cessna172 = Airplane(name: "Cessna 172")

tower.register(aircraft: boeing747)
tower.register(aircraft: airbusA380)
tower.register(aircraft: cessna172)

boeing747.send(message: "Requesting permission to land")
airbusA380.send(message: "Maintaining current altitude")
cessna172.send(message: "Beginning approach to runway")

---- Output ----
Boeing 747 sends: Requesting permission to land
Airbus A380 receives: Requesting permission to land
Cessna 172 receives: Requesting permission to land

Airbus A380 sends: Maintaining current altitude
Boeing 747 receives: Maintaining current altitude
Cessna 172 receives: Maintaining current altitude

Cessna 172 sends: Beginning approach to runway
Boeing 747 receives: Beginning approach to runway
Airbus A380 receives: Beginning approach to runway

Key Points:

  1. Mediator (ControlTower): Centralizes communication between Aircraft objects
  2. Colleagues (Airplanes): Communicate only through the mediator, not directly with each other
  3. Benefits:
    • Reduces direct connections between objects
    • Centralizes control logic
    • Makes the system easier to maintain and extend
  4. Swift-specific implementation:
    • Using AnyObject constraint for reference types
    • weak reference to mediator to avoid retain cycles

This pattern is particularly useful in scenarios where many objects need to communicate in complex ways, such as chat rooms, GUI components, or as shown here, air traffic control systems.

๐Ÿ’พ Memento (Behavioral)

Captures and externalizes an objectโ€™s state for later restoration without breaking encapsulation. Enables undo/redo functionality and snapshots.
Example: Text editor undo stack, game save points, or database transactions.

iOS System Examples

let undoManager = UndoManager()
undoManager.registerUndo(withTarget: self) { 
    $0.restore(from: memento) 
}

// Core Data's Rollback
context.rollback() // Reverts to last persisted state

Letโ€™s understand with an example - Memento Pattern: State Snapshot System

Overview Captures and externalizes an objectโ€™s state for later restoration while maintaining encapsulation.

Key Components

  1. Originator - The object that produces state snapshots
  2. Memento - Immutable state container
  3. Caretaker - Manages memento history
import Foundation

// MARK: - Originator (Text Editor)
final class TextEditor {
    private var text: String
    private var cursorPosition: Int
    
    init(text: String = "") {
        self.text = text
        self.cursorPosition = text.count
    }
    
    func type(_ char: Character) {
        text.insert(char, at: text.index(text.startIndex, offsetBy: cursorPosition))
        cursorPosition += 1
        printState()
    }
    
    func delete() {
        guard cursorPosition > 0 else { return }
        text.remove(at: text.index(text.startIndex, offsetBy: cursorPosition-1))
        cursorPosition -= 1
        printState()
    }
    
    private func printState() {
        print("๐Ÿ“ [\(cursorPosition)] \(text)")
    }
    
    // MARK: Memento Creation
    func save() -> EditorMemento {
        return EditorMemento(
            text: text,
            cursor: cursorPosition,
            date: Date()
        )
    }
    
    func restore(from memento: EditorMemento) {
        self.text = memento.text
        self.cursorPosition = memento.cursorPosition
        print("โŽŒ Restored to \(memento.date.formatted()):")
        printState()
    }
}

// MARK: - Memento (State Snapshot)
struct EditorMemento {
    let text: String
    let cursorPosition: Int
    let date: Date
    
    fileprivate init(text: String, cursor: Int, date: Date) {
        self.text = text
        self.cursorPosition = cursor
        self.date = date
    }
}

// MARK: - Caretaker (Undo Manager)
final class UndoHistory {
    private var stack: [EditorMemento] = []
    
    func save(_ memento: EditorMemento) {
        stack.append(memento)
        print("๐Ÿ’พ Saved state (\(stack.count) total)")
    }
    
    func undo() -> EditorMemento? {
        guard stack.count > 1 else { return nil }
        _ = stack.popLast()
        return stack.last
    }
    
    func clear() {
        stack.removeAll()
    }
}

// MARK: - Usage Example
func demonstrateTextEditor() {
    let editor = TextEditor()
    let history = UndoHistory()
    
    // Initial save
    history.save(editor.save())
    
    // Edit document
    "Hello".forEach { editor.type($0) }
    history.save(editor.save())
    
    editor.type(" ")
    editor.type("W")
    editor.type("o")
    editor.delete() // Deletes 'o'
    editor.type("r")
    history.save(editor.save())
    
    // Undo last 2 actions
    print("\n--- Undo ---")
    if let memento = history.undo() {
        editor.restore(from: memento)
    }
    
    // Undo again
    if let memento = history.undo() {
        editor.restore(from: memento)
    }
}

// Run the demo
demonstrateTextEditor()

/* Expected Output:
๐Ÿ“ [1] H
๐Ÿ“ [2] He
๐Ÿ“ [3] Hel
๐Ÿ“ [4] Hell
๐Ÿ“ [5] Hello
๐Ÿ’พ Saved state (2 total)
๐Ÿ“ [6] Hello 
๐Ÿ“ [7] Hello W
๐Ÿ“ [8] Hello Wo
๐Ÿ“ [7] Hello W
๐Ÿ“ [8] Hello Wr
๐Ÿ’พ Saved state (3 total)

--- Undo ---
โŽŒ Restored to 6/9/24, 3:30 PM:
๐Ÿ“ [6] Hello 

โŽŒ Restored to 6/9/24, 3:30 PM:
๐Ÿ“ [5] Hello
*/

๐Ÿ‘€ Observer (Behavioral):

Establishes a one-to-many dependency between objects so that when one object changes state, all its dependents are notified automatically.

Comparison with Similar Patterns

Pattern Relation Direction Communication Style Use Case Example
Observer One-to-many (push) Automatic broadcasts Weather updates to multiple displays
Mediator Many-to-many Centralized routing Chat room message distribution
Delegate One-to-one Direct callbacks UITableView cell configuration

Key Differences:

// Observable (Subject) class WeatherStation { @Published var temperature: Double = 20.0 // Auto-publishes changes }

// Observer let station = WeatherStation() var cancellable: AnyCancellable?

// Subscribe to changes cancellable = station.$temperature .sink { newTemp in print(โ€œ๐ŸŒก๏ธ Temperature now: (newTemp)ยฐCโ€) }

// Trigger change station.temperature = 25.0 // Observer prints automatically

/* Output: ๐ŸŒก๏ธ Temperature now: 25.0ยฐC */

Key Components:

    @Published property - The observable subject

    $ prefix access - Creates a publisher

    .sink - The observer's subscription

    AnyCancellable - Manages observation lifecycle

This is the modern Swift (Combine) way to implement Observer pattern with:

    Less boilerplate

    Type safety

    Built-in memory management

## ๐Ÿ”„ State (Behavioral)

The **State pattern** allows an object to alter its behavior when its internal state changes โ€” it appears as if the object changed its class. It's useful when an object must change behavior at runtime depending on its current state.

### ๐Ÿง‘โ€๐Ÿ’ป Swift Code Example

The State pattern is excellent for managing complex logic by encapsulating state-specific behavior into separate objects. This approach makes your code more scalable and easier to maintain than using large `switch` statements or conditional `if/else` logic. A classic example for a scalable app is a **document editor**, which can exist in various states like `Draft`, `Moderation`, and `Published`.

### Context and States

First, we need to define the **context**โ€”the object whose behavior changes based on its state. We also need to define the **state protocol** and the **concrete states**.

```swift
// State Protocol
// This defines the behavior that all concrete states must implement.
protocol DocumentState: AnyObject {
    func publish(in context: Document)
    func approve(in context: Document)
    func reject(in context: Document)
}
```

-----

### Concrete States

Each state class encapsulates the logic for a specific state. The `publish`, `approve`, and `reject` methods behave differently depending on the current state. The `context` (the `Document` instance) is passed so that the state object can change the document's state.

```swift
// Draft State
class DraftState: DocumentState {
    func publish(in context: Document) {
        print("Draft is submitted for moderation.")
        context.state = ModerationState()
    }
    
    func approve(in context: Document) {
        print("Cannot approve a draft. It must be published first.")
    }
    
    func reject(in context: Document) {
        print("Cannot reject a draft. It is not yet in moderation.")
    }
}

// Moderation State
class ModerationState: DocumentState {
    func publish(in context: Document) {
        print("Cannot publish while in moderation. You must approve it first.")
    }
    
    func approve(in context: Document) {
        print("Document is approved and published.")
        context.state = PublishedState()
    }
    
    func reject(in context: Document) {
        print("Document is rejected and sent back to draft.")
        context.state = DraftState()
    }
}

// Published State
class PublishedState: DocumentState {
    func publish(in context: Document) {
        print("Document is already published.")
    }
    
    func approve(in context: Document) {
        print("Document is already published and does not need approval.")
    }
    
    func reject(in context: Document) {
        print("Cannot reject a published document.")
    }
}
```

-----

### The Context Object

The `Document` class is the **context**. It holds a reference to the current state and delegates all actions to it. This decouples the document's main logic from the state-specific behavior.

```swift
class Document {
    var state: DocumentState
    
    init() {
        self.state = DraftState() // Initial state
    }
    
    func publish() {
        state.publish(in: self)
    }
    
    func approve() {
        state.approve(in: self)
    }
    
    func reject() {
        state.reject(in: self)
    }
}
```

### Usage

The client code interacts with the `Document` object without knowing or caring about its internal state machine. The behavior changes automatically based on the current state.

```swift
let myDocument = Document()

// Initial state: Draft
print("Current State: \(type(of: myDocument.state))") // Prints "DraftState"
myDocument.approve() // "Cannot approve a draft..."
myDocument.publish() // "Draft is submitted for moderation."

// State changed to Moderation
print("Current State: \(type(of: myDocument.state))") // Prints "ModerationState"
myDocument.reject() // "Document is rejected..."

// State changed back to Draft
print("Current State: \(type(of: myDocument.state))") // Prints "DraftState"
myDocument.publish() // "Draft is submitted for moderation."

// State changed to Moderation
print("Current State: \(type(of: myDocument.state))") // Prints "ModerationState"
myDocument.approve() // "Document is approved and published."

// Final State: Published
print("Current State: \(type(of: myDocument.state))") // Prints "PublishedState"
myDocument.publish() // "Document is already published."
```

**iOS and Apple frameworks internally use the State pattern**, especially in scenarios where **an objectโ€™s behavior changes based on its current state**. Below are real-world examples:

---

### โœ… 1. `URLSessionTask` State Management

Each task (`dataTask`, `uploadTask`, etc.) has a `state`:

```swift
public enum URLSessionTask.State {
    case running
    case suspended
    case canceling
    case completed
}
```

- The behavior of the task changes based on this state.
- You cannot resume a completed task or cancel a suspended one โ€” only allowed transitions are handled.

๐Ÿง  **State Pattern:** Each state governs what next action is valid โ€” mimicking the classic pattern.

---

### โœ… 2. `UIViewController` Lifecycle

A `UIViewController` transitions through multiple internal states:

- `viewDidLoad`
- `viewWillAppear`
- `viewDidAppear`
- `viewWillDisappear`
- `viewDidDisappear`

Each of these corresponds to different internal "states" and determines what setup or teardown logic runs.

๐Ÿง  **State Pattern:** The controller behaves differently depending on its current stage in the lifecycle.

---

### โœ… 3. `UIButton` States

A `UIButton` can be in:

- `.normal`
- `.highlighted`
- `.disabled`
- `.selected`

```swift
button.setTitle("Submit", for: .normal)
button.setTitle("Submitting...", for: .disabled)
```

Each state defines different behavior and visuals.

๐Ÿง  **State Pattern:** UIButton modifies appearance and behavior based on state automatically โ€” internal implementation leverages State-like behavior.

---

### โœ… 4. `AVPlayer`

An `AVPlayer` can be:

- Playing
- Paused
- Stopped
- Buffering

Each of these internal states modifies what actions are allowed (e.g., can't pause a stopped player).

---

### ๐Ÿ“‹ Summary

| Area         | iOS API                     | Pattern Used |
|--------------|-----------------------------|---------------|
| Networking   | `URLSessionTask.State`       | โœ… State      |
| UI Lifecycle | `UIViewController`           | โœ… State      |
| UI Controls  | `UIButton`, `UISwitch`, etc. | โœ… State      |
| Media        | `AVPlayer`                   | โœ… State      |

---
## ๐ŸŽฏ Strategy (Behavioral)

The **Strategy Pattern** is used to define a family of algorithms, encapsulate each one, and make them interchangeable. It allows the algorithm to vary independently from clients that use it.

---

### โœ… Real-World Analogy

Imagine a **Navigation App** (like Google Maps or Apple Maps). You can choose how you want to reach your destination:

- ๐Ÿš— **Fastest Route**
- ๐Ÿšฆ **Least Traffic**
- ๐ŸšŒ **Public Transport**
- ๐Ÿšถ **Walking**

Each of these is a *strategy* for navigation. The app lets you switch strategies at runtime without rewriting the logic of the app itself.

---

### ๐Ÿ’ป Swift Example

```swift
// MARK: - Strategy Protocol
protocol RouteStrategy {
    func buildRoute(from: String, to: String)
}

// MARK: - Concrete Strategies
struct FastestRoute: RouteStrategy {
    func buildRoute(from: String, to: String) {
        print("๐Ÿš— Fastest route from \(from) to \(to)")
    }
}

struct LeastTrafficRoute: RouteStrategy {
    func buildRoute(from: String, to: String) {
        print("๐Ÿš™ Least traffic route from \(from) to \(to)")
    }
}

struct PublicTransportRoute: RouteStrategy {
    func buildRoute(from: String, to: String) {
        print("๐ŸšŒ Public transport route from \(from) to \(to)")
    }
}

// MARK: - Context
class NavigationContext {
    private var strategy: RouteStrategy

    init(strategy: RouteStrategy) {
        self.strategy = strategy
    }

    func updateStrategy(_ strategy: RouteStrategy) {
        self.strategy = strategy
    }

    func navigate(from: String, to: String) {
        strategy.buildRoute(from: from, to: to)
    }
}
```

---

### ๐Ÿงช Usage

```swift
let nav = NavigationContext(strategy: FastestRoute())
nav.navigate(from: "Home", to: "Work")

nav.updateStrategy(LeastTrafficRoute())
nav.navigate(from: "Home", to: "Work")

nav.updateStrategy(PublicTransportRoute())
nav.navigate(from: "Home", to: "Work")
```

---

### ๐Ÿ“ฆ Benefits

- Promotes **Open/Closed Principle** โ€” add new strategies without modifying existing code.
- Helps separate concerns โ€” algorithm logic is decoupled from usage.
- Easily testable and extendable.

---

### ๐Ÿ“ฑ Where It's Used in iOS

- `UICollectionView` / `UITableView` uses different *layout strategies* (`UICollectionViewFlowLayout`, `UICollectionViewCompositionalLayout`)
- `UIViewControllerTransitioningDelegate` allows different transition *animation strategies*

---
<a id="template-method"></a>
## ๐Ÿ“ Template-Method-(Behavioral)

The **Template Method** pattern defines the *skeleton* of an algorithm in a base class, while allowing subclasses to redefine specific steps without changing the algorithm's overall structure.

This promotes **code reuse**, enforces **consistent workflows**, and allows flexibility in extending behavior where needed.

---

### โœ… When to Use

- When multiple classes share the same algorithm structure but differ in specific steps.
- When you want to avoid code duplication while allowing extensions.

---

### ๐Ÿš€ Real-World Example

#### ๐Ÿ“ฆ Online Order Processing(test)

```swift
class OrderProcessTemplate {
    func processOrder() {
        selectItems()
        makePayment()
        shipItems()
        sendReceipt()
    }

    func selectItems() {
        print("Items selected")
    }

    func makePayment() {
        fatalError("Subclass must override makePayment()")
    }

    func shipItems() {
        print("Items shipped")
    }

    func sendReceipt() {
        print("Receipt sent")
    }
}

class OnlineOrder: OrderProcessTemplate {
    override func makePayment() {
        print("Paid using UPI")
    }
}

let order = OnlineOrder()
order.processOrder()

๐ŸŽ iOS Built-in Example

UIKit uses the Template Method pattern extensively. For example:

๐Ÿงฑ UITableView

Apple defines the structure of rendering a table, but developers customize specific steps via delegate methods:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

Apple calls the template lifecycle internally, but gives you hooks to override critical steps.


๐Ÿงฉ Summary

Role Description
Abstract Class Defines the template method and default steps
Subclass Overrides one or more steps to provide specific behavior

โœ… Helps maintain algorithm consistency while offering flexibility for customization.


๐Ÿ‘ฃ Visitor (Behavioral)

The Visitor pattern allows you to add new operations to a group of objects without changing their classes. Instead of adding logic to the objects, you create a separate visitor that implements the operation.


โœ… When to Use


๐Ÿ’ก Real-World Example

๐Ÿ“„ Document Exporter

protocol Document {
    func accept(visitor: DocumentVisitor)
}

class PDFDocument: Document {
    func accept(visitor: DocumentVisitor) {
        visitor.visit(pdf: self)
    }
}

class WordDocument: Document {
    func accept(visitor: DocumentVisitor) {
        visitor.visit(word: self)
    }
}

protocol DocumentVisitor {
    func visit(pdf: PDFDocument)
    func visit(word: WordDocument)
}

class PrintVisitor: DocumentVisitor {
    func visit(pdf: PDFDocument) {
        print("๐Ÿ–จ๏ธ Printing PDF Document")
    }

    func visit(word: WordDocument) {
        print("๐Ÿ–จ๏ธ Printing Word Document")
    }
}

๐Ÿงช Usage:

let documents: [Document] = [PDFDocument(), WordDocument()]
let printer = PrintVisitor()

for doc in documents {
    doc.accept(visitor: printer)
}

๐ŸŽ iOS Built-in Usage

While iOS doesnโ€™t explicitly use the Visitor pattern, similar behavior can be seen in:


๐Ÿงฉ Summary

Role Description
Visitor Declares visit() methods for each concrete type
Element Has an accept(visitor:) method
ConcreteVisitor Implements actions to be taken on each element

โœ… The Visitor pattern promotes open/closed principle by letting you add new operations without modifying existing classes.