객체간의 일대다 관계, 느슨한 결합이 핵심.
public class WeatherData {
//인스턴스 변수 선언
let currentConditionsDisplay: UIView
let statisticsDisplay: UIView
let forecastDisplay: UIView
init(currentConditionsDisplay: CurrentConditionsDisplay, statisticsDisplay: StatisticsDisplay, forecastDisplay: ForecastDisplay ) {
self.currentConditionsDisplay = currentConditionsDisplay
self.statisticsDisplay = statisticsDisplay
self.forecastDisplay = forecastDisplay
}
//기상 스테이션이 WeatherData에게 값 변경을 알려줄 때 사용되는 메서드
public func measurementsChanged() {
let temp: Float = getTemperature()
let humidity: Float = getHumidity()
let pressure: Float = getPressure()
//1
currentConditionsDisplay.update(temp, humidity, pressure)
statisticsDisplay.update(temp, humidity, pressure)
forecastDisplay.update(temp, humidity, pressure)
}
}
WeatherData
에게 measurementsChanged()
메서드를 이용해서 전달합니다.measurementsChanged()
메서드가 호출되면 WeatherData는 내부에 생성된 세가지 View에게 값을 update할 것을 명령합니다.문제점
옵저버 패턴에서는 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one - to - many)의존성을 정의합니다.
Subject 인터페이스
ConcreteSubject
Observer 인터페이스
ConcreteObserver
[Subject]
import Foundation
//Subject 인터페이스
protocol Subjectable {
var observers: [Observable] { get set }
func registerObserver(observer: Observable)
func removeObserver(observer: Observable)
func notifyObservers()
}
//Subject 구현체
class WeatherData: Subjectable {
var observers: [Observable] = []
var temperature: Float = 0.0
var humidity: Float = 0.0
var pressure: Float = 0.0
func registerObserver(observer: Observable) { observers.append(observer) }
func removeObserver(observer: Observable) {
if let index = self.observers.firstIndex(where: { $0.id == observer.id }) {
self.observers.remove(at: index)
}
}
func notifyObservers() {
observers.forEach{
$0.update(temperature: temperature, humidity: humidity, pressure: pressure)
}
}
func measurementsChanged() {
notifyObservers()
}
func setMeasurements(temperature: Float, humidity: Float, pressure: Float) {
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
measurementsChanged()
}
deinit { observers.removeAll() }
}
[Observer]
//Observer 인터페이스
protocol Observable {
var id: String { get set }
func update(temperature: Float, humidity: Float, pressure: Float)
}
//Observer 구현체 - 현재 조건 Display
class CurrentCondtionsDisplay: Observable {
var id: String
let subject: Subjectable
private var temperature: Float = 0.0
private var humidity: Float = 0.0
private var pressure: Float = 0.0
init(id: String, subject: Subjectable) {
self.id = id
self.subject = subject
subject.registerObserver(observer: self)
}
func update(temperature: Float, humidity: Float, pressure: Float) {
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
display()
}
func display() {
print("Current conditions: \(temperature) F degrees and humidity \(humidity) ")
}
deinit { subject.removeObserver(observer: self) }
}
//Observer 구현체 - 기상 통계 display
class StatisticsDisplay: Observable {
var id: String
let subject: Subjectable
private var temperature: Float = 0.0
private var humidity: Float = 0.0
private var pressure: Float = 0.0
init(id: String, subject: Subjectable) {
self.id = id
self.subject = subject
subject.registerObserver(observer: self)
}
func update(temperature: Float, humidity: Float, pressure: Float) {
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
display()
}
func display() {
print("Statistics : \(temperature) F degrees and humidity \(humidity) ")
}
deinit { subject.removeObserver(observer: self) }
}
//Observer 구현체 - 기상예측 display
class ForecastDisplay: Observable {
var id: String
let subject: Subjectable
private var temperature: Float = 0.0
private var humidity: Float = 0.0
private var pressure: Float = 0.0
init(id: String, subject: Subjectable) {
self.id = id
self.subject = subject
subject.registerObserver(observer: self)
}
func update(temperature: Float, humidity: Float, pressure: Float) {
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
display()
}
func display() {
print("Forecast : \(temperature) F degrees and humidity \(humidity) ")
}
deinit { subject.removeObserver(observer: self) }
}
//Main
let weatherData = WeatherData()
let currentCondtionsDisplay = CurrentCondtionsDisplay(id: "CurrentCondtionsDisplay", subject: weatherData)
let statisticsDisplay = StatisticsDisplay(id: "StatisticsDisplay", subject: weatherData)
let forecastDisplay = ForecastDisplay(id: "ForecastDisplay", subject: weatherData)
subject.setMeasurements(temperature: 56.1, humidity: 27.3, pressure: 22.1)
[Result]
---결과----
Current conditions: 56.1 F degrees and humidity 27.3
Statistics : 56.1 F degrees and humidity 27.3
Forecast : 56.1 F degrees and humidity 27.3
디자인 원칙
서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.