안녕하세요 bulmang입니다. Swift 패턴에 대해 알아보고 정리해봤습니다, 틀린 부분이 있으면 알려주시면 감사하겠습니다.
Swift에서 패턴은 코드에서 반복되는 공통적인 구조를 식별하는 방법입니다.
패턴은 코드를 작성할 때 일관성 있게 사용하므로 코드의 가독성과 유지보수성을 향상시키는 데 도움이 됩니다.
Decorator 패턴
Decorator 패턴은 객체의 기능을 동적으로 확장하는 방법입니다. 이 패턴은 객체를 래핑하고, 래핑된 객체와 동일한 인터페이스를 제공하여 기능을 추가하거나 수정합니다. 이 패턴은 객체의 변경이나 확장을 클래스의 서브 클래스 생성을 통해 하지 않고, 런타임에 유연하게 처리할 수 있습니다. 예를 들어, 다음은 커피에 시럽을 추가하는 예제 코드입니다.
protocol Coffee {
var description: String { get }
var cost: Double { get }
}
class BasicCoffee: Coffee {
var description: String {
return "Basic Coffee"
}
var cost: Double {
return 1.0
}
}
class SyrupDecorator: Coffee {
private let baseCoffee: Coffee
private let syrupCost: Double
var description: String {
return "\\(baseCoffee.description) with syrup"
}
var cost: Double {
return baseCoffee.cost + syrupCost
}
init(baseCoffee: Coffee, syrupCost: Double) {
self.baseCoffee = baseCoffee
self.syrupCost = syrupCost
}
}
let basicCoffee = BasicCoffee()
let coffeeWithSyrup = SyrupDecorator(baseCoffee: basicCoffee, syrupCost: 0.5)
print(coffeeWithSyrup.description) // "Basic Coffee with syrup"
print(coffeeWithSyrup.cost) // 1.5
위의 예제 코드에서 **Coffee**는 추상화된 커피를 나타내는 프로토콜입니다. BasicCoffee 클래스는 Coffee 프로토콜을 채택하여 기본 커피에 대한 구현을 제공합니다. SyrupDecorator 클래스는 Coffee 프로토콜을 채택하고, 래핑된 Coffee 객체를 가져와 시럽을 추가합니다. SyrupDecorator 클래스는 baseCoffee 및 syrupCost 매개 변수를 사용하여 BasicCoffee 인스턴스를 래핑합니다. description 및 cost 속성을 오버라이드하여, 래핑된 **BasicCoffee**의 속성과 **SyrupDecorator**의 추가 속성을 결합합니다.
위의 예제 코드에서 **basicCoffee**는 BasicCoffee 클래스의 인스턴스입니다. **coffeeWithSyrup**은 **basicCoffee**를 래핑하는 SyrupDecorator 클래스의 인스턴스입니다. 이를 통해 coffeeWithSyrup 객체는 **BasicCoffee**와 동일한 Coffee 인터페이스를 제공하면서, 시럽이 추가된 기능을 제공합니다.
Observer 패턴
Observer 패턴은 객체 간의 의존성을 최소화하고, 객체 상태의 변화를 다른 객체에게 알리는 방법입니다. 이 패턴은 객체 간의 결합도를 줄이고, 유연한 코드를 작성할 수 있게 합니다. 예를 들어, 다음은 간단한 Observer 패턴 예제 코드입니다.
protocol Subject {
func attach(observer: Observer)
func detach(observer: Observer)
func notify()
}
protocol Observer {
func update(subject: Subject)
}
class WeatherStation: Subject {
private var observers = [Observer]()
private var temperature: Double = 0.0
func attach(observer: Observer) {
observers.append(observer)
}
func detach(observer: Observer) {
if let index = observers.firstIndex(where: { $0 === observer }) {
observers.remove(at: index)
}
}
func notify() {
for observer in observers {
observer.update(subject: self)
}
}
func updateTemperature(temp: Double) {
self.temperature = temp
notify()
}
func getTemperature() -> Double {
return temperature
}
}
class PhoneDisplay: Observer {
private var weatherStation: WeatherStation
init(weatherStation: WeatherStation) {
self.weatherStation = weatherStation
self.weatherStation.attach(observer: self)
}
func update(subject: Subject) {
if let weatherStation = subject as? WeatherStation {
print("Phone display: Temperature is \\(weatherStation.getTemperature())")
}
}
}
let weatherStation = WeatherStation()
let phoneDisplay = PhoneDisplay(weatherStation: weatherStation)
weatherStation.updateTemperature(temp: 20.0) // "Phone display: Temperature is 20.0"
위의 예제 코드에서 **Subject**는 주제를 나타내는 프로토콜입니다. **Observer**는 관찰자를 나타내는 프로토콜입니다. WeatherStation 클래스는 Subject 프로토콜을 채택하고, Observer 객체를 관리합니다. PhoneDisplay 클래스는 Observer 프로토콜을 채택하고, WeatherStation 객체를 구독합니다.
updateTemperature 메서드는 WeatherStation 객체의 온도를업데이트하고, notify 메서드를 호출하여 등록된 모든 Observer 객체에게 온도 변화를 알립니다. PhoneDisplay 클래스는 Observer 프로토콜의 update 메서드를 구현하여, WeatherStation 객체로부터 전달된 온도 정보를 출력합니다.
Singleton 패턴
Singleton 패턴은 애플리케이션에서 하나의 인스턴스만 존재해야 하는 클래스를 구현할 때 사용됩니다. 이 패턴을 사용하면, 인스턴스의 생성 및 소멸을 제어할 수 있고, 전역 변수와 같이 어디에서나 접근 가능한 객체를 만들 수 있습니다. 다음은 간단한 Singleton 패턴 예제 코드입니다.
class MySingleton {
static let shared = MySingleton()
private init() {}
func doSomething() {
print("Doing something...")
}
}
MySingleton.shared.doSomething() // "Doing something..."
위의 예제 코드에서 MySingleton 클래스는 Singleton 패턴을 구현합니다. shared 속성은 클래스의 인스턴스를 반환합니다. init 메서드는 비공개로 설정되어, 인스턴스의 생성을 제어합니다. doSomething 메서드는 클래스의 인스턴스에서 수행할 작업을 정의합니다.
Factory 패턴
Factory 패턴은 객체 생성을 캡슐화하여, 코드의 유연성과 확장성을 높입니다. 이 패턴을 사용하면, 객체 생성을 담당하는 클래스를 작성하여, 객체 생성 코드를 캡슐화할 수 있습니다. 다음은 간단한 Factory 패턴 예제 코드입니다.
protocol Animal {
func speak()
}
class Dog: Animal {
func speak() {
print("Woof!")
}
}
class Cat: Animal {
func speak() {
print("Meow!")
}
}
enum AnimalType {
case dog
case cat
}
class AnimalFactory {
static func createAnimal(type: AnimalType) -> Animal {
switch type {
case .dog:
return Dog()
case .cat:
return Cat()
}
}
}
let animal1 = AnimalFactory.createAnimal(type: .dog)
animal1.speak() // "Woof!"
let animal2 = AnimalFactory.createAnimal(type: .cat)
animal2.speak() // "Meow!"
위의 예제 코드에서 Animal 프로토콜은 동물을 나타내며, speak 메서드를 정의합니다. Dog 및 Cat 클래스는 Animal 프로토콜을 구현하고, speak 메서드를 재정의합니다.
**AnimalType**은 동물의 종류를 열거형으로 정의합니다. AnimalFactory 클래스는 createAnimal 메서드를 사용하여, Animal 객체를 생성합니다. 이 메서드는 AnimalType 매개 변수를 사용하여, 생성할 동물의 종류를 결정합니다.
'SwiftUI > 정리' 카테고리의 다른 글
[Swift] 기본 문법 정리 (0) | 2023.03.19 |
---|---|
[Swift] 첫 iOS 앱 개발자를 위한 가이드 from Lingo (0) | 2023.03.13 |
[SwiftUI] Geometry (0) | 2023.02.23 |
info.plist 사라지는 문제 (0) | 2023.02.16 |
SwiftUI - Stack (0) | 2021.03.10 |