안녕하세요! 이번에는 디자인 패턴 중 하나인 옵저버 패턴(Observer Pattern)에 대해 알아보려고 해요. 옵저버 패턴은 소프트웨어 개발에서 자주 사용되는 유용한 아이디어 중 하나로, 객체들 사이의 상호작용을 효과적으로 구현하는 방법을 제공하는 패턴입니다. 옵저버 패턴에 대한 개념과 특징을 자세히 한 번 알아보고 Swift와 Java, JavaScript 이렇게 각 언어별로 예시 소스까지 살펴보도록 하겠습니다!
옵저버 패턴이란?
옵저버 패턴은 한 객체의 상태 변화가 다른 여러 객체들에게 자동으로 알림을 보내고, 그들이 필요한 처리를 할 수 있도록 하는 디자인 패턴입니다. 주체(Subject)와 옵저버(Observer)라는 두 가지 주요 역할로 구성되며, 직접적인 결합 없이 유연하게 상호작용할 수 있습니다.
- 주요 구성 요소
- Subject (주체): 상태 변화를 감지하고 등록된 모든 옵저버들에게 알림을 보내는 역할을 합니다.
- Observer (옵저버): 주체로부터 전달받은 알림을 처리하기 위한 인터페이스를 제공합니다.
- ConcreteSubject (구체적인 주체): Subject 클래스를 구현하며, 실제로 상태 변화가 발생하는 객체입니다.
- ConcreteObserver (구체적인 옵저버): Observer 인터페이스를 구현하여 실제로 알림을 받고 처리하는 객체입니다.
옵저버 패턴의 예시
예를 들어, 여러분들이 게시판 프로그램을 만들 때 게시판 서비스에서 새로운 글이 작성될 때마다 사용자들에게 알림을 보내야 한다고 생각해봅시다. 이때 게시판 서비스는 Subject 역할을 하며, 사용자들은 Observer 역할을 합니다. 게시글 작성 시 Subject는 등록된 모든 Observer에게 알림 메시지를 전송하여 사용자들이 새 글에 대해 반응할 수 있도록 도와줍니다.
장단점
장점
- 주체와 옵저버 간의 느슨한 결합 : 주체와 옵서베 사이의 직간섭 없이 유연하게 확장 가능합니다.
- 확장성과 유연성 : 새로운 주체 및 옵서베 클래스 추가 및 수정이 용이합니다.
- 동기 및 비동기 처리 가능 : 여러 개의 동기 또는 비동기적으로 동작하는 여러 개의 옵서베들 조합하여 다양한 기능 구현 가능합니다.
단점
- 너무 많은 업데이트 호출 : 많은 수의 등록된 옵서베가 있는 경우 성능 저하 문제가 발생할 수 있습니다.
- 순환 종속성 문제 : 서로 참조하여 순환 종속성 문제가 발생할 수 있으므로 조심해야 합니다.
예외 상황과 대처 방안 예외 상황에서도 안정적으로 동작하기 위해서 몇 가지 고려사항이 있습니다.
- 등록/해지 과정에서 예외 처리 필요
- 메모리 누수 방지 위해 WeakReference 등 활용
Swift에서의 옵저버 패턴
import Foundation
// 관찰자 및 주제를 정의하는 프로토콜
protocol Observer {
func update(temperature: Double, humidity: Double, pressure: Double)
}
protocol Subject {
func registerObserver(observer: Observer)
func removeObserver(observer: Observer)
func notifyObservers()
}
// 날씨 데이터는 관찰자들에게 알릴 주제입니다
class WeatherData: Subject {
private var temperature: Double = 0.0
private var humidity: Double = 0.0
private var pressure: Double = 0.0
private var observers: [Observer] = []
func registerObserver(observer: Observer) {
observers.append(observer)
}
func removeObserver(observer: Observer) {
if let index = observers.firstIndex(where: { $0 === observer }) {
observers.remove(at: index)
}
}
func notifyObservers() {
for observer in observers {
observer.update(temperature: temperature, humidity: humidity, pressure: pressure)
}
}
func setMeasurements(temperature: Double, humidity: Double, pressure: Double) {
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
measurementsChanged()
}
func measurementsChanged() {
notifyObservers()
}
}
// 구체적인 관찰자
class CurrentConditionsDisplay: Observer {
func update(temperature: Double, humidity: Double, pressure: Double) {
print("현재 날씨: \(temperature)도, 습도 \(humidity)%")
}
}
// 예제 사용
let weatherData = WeatherData()
let currentDisplay = CurrentConditionsDisplay()
weatherData.registerObserver(observer: currentDisplay)
weatherData.setMeasurements(temperature: 75.0, humidity: 60.0, pressure: 30.4)
이 Swift 소스는 옵저버 패턴을 사용하여 날씨 모니터링 시스템을 구현하는 소스입니다.
- Observer 및 Subject 프로토콜은 관찰자와 주제를 정의합니다.
- WeatherData 클래스는 주제 역할을 하며 온도, 습도, 기압 데이터를 관찰자에게 알립니다.
- CurrentConditionsDisplay는 구체적인 관찰자로서 현재 날씨 정보를 출력합니다.
- 예제에서는 날씨 데이터 객체를 생성하고 현재 날씨 디스플레이를 등록한 후, 날씨 데이터의 측정값을 설정하여 관찰자에게 알립니다.
Java에서의 옵저버 패턴
import java.util.ArrayList;
import java.util.List;
// 관찰자 인터페이스
interface Observer {
void update(double temperature, double humidity, double pressure);
}
// 주제 인터페이스
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// WeatherData는 구체적인 주제입니다
class WeatherData implements Subject {
private List<Observer> observers = new ArrayList<>();
private double temperature;
private double humidity;
private double pressure;
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void setMeasurements(double temperature, double humidity, double pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public void measurementsChanged() {
notifyObservers();
}
}
// 구체적인 관찰자
class CurrentConditionsDisplay implements Observer {
public void update(double temperature, double humidity, double pressure) {
System.out.println("현재 날씨: " + temperature + "도, 습도 " + humidity + "%");
}
}
// 예제 사용
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
weatherData.registerObserver(currentDisplay);
weatherData.setMeasurements(75.0, 60.0, 30.4);
}
}
이 Java 소스도 날씨 모니터링 시스템을 구현하며 옵저버 패턴을 사용하는 소스입니다!
- Observer 인터페이스는 관찰자의 역할을 정의하고, Subject 인터페이스는 주제의 역할을 정의합니다.
- WeatherData 클래스는 구체적인 주제 역할을 하며 온도, 습도, 기압 데이터를 관찰자에게 알립니다.
- CurrentConditionsDisplay는 구체적인 관찰자로 현재 날씨 정보를 출력합니다.
- 예제에서는 날씨 데이터 객체를 생성하고 현재 날씨 디스플레이를 등록한 후, 날씨 데이터의 측정값을 설정하여 관찰자에게 알립니다.
JavaScript에서의 옵저버 패턴
// 관찰자 함수
function Observer() {
this.update = function(temperature, humidity, pressure) {
console.log("현재 날씨: " + temperature + "도, 습도 " + humidity + "%");
};
}
// 주제 함수
function Subject() {
this.observers = [];
this.registerObserver = function(observer) {
this.observers.push(observer);
};
this.removeObserver = function(observer) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
};
this.notifyObservers = function() {
for (const observer of this.observers) {
observer.update(this.temperature, this.humidity, this.pressure);
}
};
}
// WeatherData는 구체적인 주제입니다
function WeatherData() {
Subject.call(this);
this.temperature = 0;
this.humidity = 0;
this.pressure = 0;
this.setMeasurements = function(temperature, humidity, pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
this.measurementsChanged();
};
this.measurementsChanged = function() {
this.notifyObservers();
};
}
// 예제 사용
const weatherData = new WeatherData();
const currentDisplay = new Observer();
weatherData.registerObserver(currentDisplay);
weatherData.setMeasurements(75.0, 60.0, 30.4);
이 JavaScript 소스 역시 옵저버 패턴을 사용하여 날씨 모니터링 시스템을 구현하는 소스입니다!
- Observer 함수는 관찰자의 역할을 정의하고, Subject 함수는 주제의 역할을 정의합니다.
- WeatherData 함수는 구체적인 주제 역할을 하며 온도, 습도, 기압 데이터를 관찰자에게 알립니다.
- CurrentConditionsDisplay는 구체적인 관찰자로 현재 날씨 정보를 출력합니다.
- 예제에서는 날씨 데이터 객체를 생성하고 현재 날씨 디스플레이를 등록한 후, 날씨 데이터의 측정값을 설정하여 관찰자에게 알립니다.
이번 포스팅에서는 옵저버 패턴(Observer Pattern)을 다루어 보았습니다.
정리해보자면 옵저버 패턴은 객체 간의 느슨한 결합을 유지하면서 주제(Subject)와 관찰자(Observer) 간의 상호 작용을 관리하는 데 사용됩니다. 이를 통해 주제의 상태가 변경될 때 관찰자에게 알릴 수 있으며, 여러 관찰자들이 동시에 주제의 변화를 감지할 수 있습니다.
옵저버 패턴은 소프트웨어 설계에서 자주 사용되며, 이 패턴을 활용하면 코드의 유지보수성과 확장성을 향상시킬 수 있습니다. 이러한 디자인 패턴을 잘 이해하고 활용하면, 더 효과적인 소프트웨어 개발에 도움이 될 수 있습니다!
감사합니다.
틀린 부분이 있거나 더 좋은 내용 훈수 환영합니다!
공감과 댓글 부탁드립니다.
'CS > 디자인 패턴' 카테고리의 다른 글
[디자인패턴] MVC 패턴 이해하고 활용하기 (0) | 2024.01.15 |
---|---|
[디자인패턴] 이터레이터 패턴 With Swift, Java (0) | 2023.10.29 |
[디자인패턴] 프록시 패턴(Proxy Pattern) (2) | 2023.10.22 |
[디자인 패턴] 팩토리 패턴과 전략 패턴의 개념과 예제 소스 (2) | 2023.10.02 |
[디자인 패턴] 디자인 패턴과 싱글톤 패턴 (2) | 2023.05.24 |