Swift에서 디자인 패턴 구현하기: 싱글턴, 옵저버, 팩토리 패턴 등 Swift 맞춤 디자인 패턴 심층 분석.

작성일 :

Swift에서 디자인 패턴 구현하기: 싱글턴, 옵저버, 팩토리 패턴 등 Swift 맞춤 디자인 패턴 심층 분석

Swift는 Apple의 iOS, macOS, watchOS 및 tvOS 애플리케이션 개발을 위해 만들어진 프로그래밍 언어로, 높은 성능과 안전성을 제공하는 동시에 사용하기 쉬운 언어로 설계되었습니다. 이 글에서는 Swift에서 디자인 패턴을 어떻게 구현할 수 있는지에 대해 알아보고, 대표적인 싱글턴(Singleton), 옵저버(Observer), 팩토리(Factory) 패턴을 심층 분석하겠습니다.

싱글턴 패턴

개요

싱글턴 패턴(Singleton)은 클래스의 인스턴스가 하나만 생성되고, 호출될 때마다 동일한 인스턴스를 반환하는 패턴입니다. 이 패턴은 전역 변수를 대신하여 사용할 수 있으며, 인스턴스가 애플리케이션 내에서 고유한 상태를 유지해야 할 때 유용합니다.

구현 방법

Swift에서 싱글턴 패턴을 구현하는 것은 매우 간단합니다. static 키워드와 private init() 메서드를 사용하여 클래스의 인스턴스가 하나만 생성되도록 보장할 수 있습니다.

swift
class Singleton {
    static let shared = Singleton()
    private init() {}
    func doSomething() {
        print("Doing something...")
    }
}

let singleton = Singleton.shared
singleton.doSomething()

위 코드는 Singleton 클래스의 인스턴스가 오직 하나만 존재하도록 보장합니다. shared라는 정적 속성에 인스턴스를 저장하고, 외부에서 직접 인스턴스를 생성하지 못하도록 init 메서드를 private으로 선언합니다.

옵저버 패턴

개요

옵저버 패턴(Observer)은 객체의 상태 변화를 관찰하는 옵저버들이 있고, 상태가 변할 때마다 자동으로 모든 옵저버들에게 통보되는 패턴입니다. 이 패턴은 주로 이벤트 처리 시스템에서 사용됩니다.

구현 방법

Swift에서 옵저버 패턴을 구현하려면 프로토콜(protocol)과 델리게이트(delegate) 패턴을 함께 사용합니다.

swift
protocol Observer {
    func update(subject: Any)
}

class Subject {
    var observers = [Observer]()
    var state: Int = { didSet { notifyObservers() } }()
    func addObserver(observer: Observer) {
        observers.append(observer)
    }
    private func notifyObservers() {
        for observer in observers {
            observer.update(subject: self)
        }
    }
}

class ConcreteObserver: Observer {
    func update(subject: Any) {
        if let subject = subject as? Subject {
            print("State has changed to: \(subject.state)")
        }
    }
}

let subject = Subject()
let observer = ConcreteObserver()
subject.addObserver(observer: observer)
subject.state = 10

위의 코드는 옵저버 패턴을 구현한 예입니다. Observer 프로토콜은 update 메서드를 요구하고, Subject 클래스는 옵저버 목록을 유지하며 상태가 변경될 때마다 옵저버들에게 통보합니다.

팩토리 패턴

개요

팩토리 패턴(Factory)은 객체 생성 로직을 캡슐화하여 클라이언트 코드와 객체 생성 코드를 분리하는 패턴입니다. 이 패턴은 객체 생성의 원천을 감추고, 생성할 객체의 타입을 런타임에 결정하는 데 유용합니다.

구현 방법

Swift에서 팩토리 패턴을 구현하려면 프로토콜과 클래스 메서드를 함께 사용할 수 있습니다.

swift
protocol Product {
    func use()
}

class ConcreteProductA: Product {
    func use() {
        print("Using Product A")
    }
}

class ConcreteProductB: Product {
    func use() {
        print("Using Product B")
    }
}

class Factory {
    enum ProductType {
        case A
        case B
    }

    static func createProduct(type: ProductType) -> Product {
        switch type {
        case .A:
            return ConcreteProductA()
        case .B:
            return ConcreteProductB()
        }
    }
}

let productA = Factory.createProduct(type: .A)
productA.use()

let productB = Factory.createProduct(type: .B)
productB.use()

위 코드는 팩토리 패턴을 사용하여 Product 객체를 생성하는 예입니다. Product 프로토콜은 use 메서드를 요구하고, ConcreteProductAConcreteProductB 클래스는 이를 구현합니다. Factory 클래스의 createProduct 메서드는 입력된 타입에 따라 올바른 제품 객체를 생성하여 반환합니다.

결론

Swift에서 디자인 패턴을 사용하는 것은 코드의 재사용성을 높이고, 유지보수를 용이하게 하며, 코드 품질을 향상시키는 데 매우 유용합니다. 싱글턴, 옵저버, 팩토리 패턴은 이러한 목표를 달성하는 데 도움이 되는 대표적인 패턴들입니다. 각 패턴의 개념과 구현 방법을 명확히 이해함으로써 더욱 효율적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.