옵저버(Observer) 패턴
2024. 10. 3. 18:50ㆍDesign Pattern
디자인 패턴: Observer 패턴
Observer 패턴은 객체들 간의 일대다(one-to-many) 관계를 정의하여, 하나의 객체 상태가 변할 때 의존하는 객체들(구독자, observers)이 자동으로 알림을 받고 갱신될 수 있도록 하는 디자인 패턴입니다. 이 패턴은 행위 패턴(Behavioral Patterns) 중 하나로, 객체 사이의 결합도를 줄여서 시스템의 확장성과 유지보수성을 높이는 데 기여합니다.
Observer 패턴의 개념
Observer 패턴은 주체(Subject)와 관찰자(Observer) 간의 관계를 설정하여 주체의 상태가 변할 때 관찰자들에게 통지(알림)하는 방식으로 동작합니다. 이를 통해 주체 객체는 구체적으로 어떤 객체들이 자신을 구독하고 있는지 알 필요 없이,
느슨한 결합(loose coupling)을 유지할 수 있습니다.
주요 구성 요소
- Subject (주체)
- 상태를 관리하고, 상태가 변경되면 Observer에게 알림을 보냅니다.
- Observer들을 등록하고 제거할 수 있는 메서드를 제공합니다.
- Observer (관찰자)
- Subject의 상태 변화를 감지하고, 그에 따라 동작을 수행합니다.
- 주체로부터 상태 변경 알림을 받으면, 관련 메서드를 호출하여 갱신합니다.
- ConcreteSubject (구체적인 주체)
- Subject의 구체적인 구현체로, 상태를 관리하고 변경 시 Observer에게 알림을 전송합니다.
- ConcreteObserver (구체적인 관찰자)
- Observer의 구체적인 구현체로, Subject의 상태 변화를 기반으로 특정 행동을 수행합니다.
Observer 패턴 구현 예시
1. Subject와 Observer 인터페이스 정의
// Observer 인터페이스
public interface IObserver
{
void Update(string message);
}
// Subject 인터페이스
public interface ISubject
{
void Attach(IObserver observer); // Observer 등록
void Detach(IObserver observer); // Observer 해제
void Notify(); // Observer들에게 알림 전송
}
2. 구체적인 주체(ConcreteSubject) 클래스
public class ConcreteSubject : ISubject
{
private List<IObserver> observers = new List<IObserver>();
private string message;
// Observer 등록
public void Attach(IObserver observer)
{
observers.Add(observer);
}
// Observer 해제
public void Detach(IObserver observer)
{
observers.Remove(observer);
}
// 상태 변화 알림
public void Notify()
{
foreach (var observer in observers)
{
observer.Update(message);
}
}
// 주체의 상태 변경
public void UpdateMessage(string newMessage)
{
message = newMessage;
Notify(); // 상태가 변경되면 알림 전송
}
}
3. 구체적인 관찰자(ConcreteObserver) 클래스
public class ConcreteObserver : IObserver
{
private string observerName;
public ConcreteObserver(string name)
{
observerName = name;
}
// 알림을 받으면 수행할 작업
public void Update(string message)
{
Console.WriteLine($"{observerName} received message: {message}");
}
}
4. Observer 패턴 실행 예시
class Program
{
static void Main(string[] args)
{
// 주체 생성
ConcreteSubject subject = new ConcreteSubject();
// 관찰자 생성 및 등록
IObserver observer1 = new ConcreteObserver("Observer 1");
IObserver observer2 = new ConcreteObserver("Observer 2");
subject.Attach(observer1);
subject.Attach(observer2);
// 주체의 상태 변경
subject.UpdateMessage("Message 1");
subject.UpdateMessage("Message 2");
// Observer 1 해제 후 새로운 상태 업데이트
subject.Detach(observer1);
subject.UpdateMessage("Message 3");
}
}
출력 결과:
Observer 1 received message: Message 1
Observer 2 received message: Message 1
Observer 1 received message: Message 2
Observer 2 received message: Message 2
Observer 2 received message: Message 3
Observer 패턴의 장점
- 느슨한 결합 (Loose Coupling)
- Subject와 Observer 간의 결합도가 낮아, 시스템의 구조를 변경해도 양쪽에 큰 영향을 주지 않습니다.
- 확장성
- 새로운 Observer를 쉽게 추가할 수 있으며, Subject의 기능을 변경하지 않고도 Observer 간의 관계를 확장할 수 있습니다.
- 실시간 업데이트
- 주체의 상태가 변경될 때마다 즉시 Observer에게 알림을 전송하므로, 실시간 상태 업데이트가 가능합니다.
Observer 패턴의 단점
- 성능 이슈
- 많은 Observer가 구독 중일 때, 주체가 상태를 변경할 때마다 모든 Observer에게 알림을 전송해야 하므로 성능에 부담이 될 수 있습니다.
- 복잡성 증가
- 다수의 Observer와 주체 간의 관계를 관리해야 하므로 복잡한 구조를 형성할 수 있습니다.
Observer 패턴의 사용 사례
Observer 패턴은 여러 상황에서 활용됩니다. 대표적인 예시는 다음과 같습니다.
- 이벤트 기반 시스템: GUI 애플리케이션에서 버튼 클릭이나 사용자 입력 이벤트를 처리할 때, 이벤트 리스너(Observer)가 상태 변화를 감지하고 작업을 수행합니다.
- 실시간 데이터 업데이트: 주식 거래 시스템, 소셜 미디어 알림 등에서 데이터를 실시간으로 업데이트하고 이를 구독자들에게 전송할 때 사용됩니다.
- MVC 패턴: Model-View-Controller 패턴에서, 모델의 데이터가 변경되면 뷰에 이를 반영하는 역할로 Observer 패턴을 사용할 수 있습니다.
Observer 패턴은 객체들 간의 느슨한 결합을 유지하면서 상태 변화를 구독자들에게 자동으로 알릴 수 있는 강력한 패턴입니다. 실시간 데이터 업데이트, 이벤트 리스닝 등 다양한 상황에서 활용될 수 있으며, 확장 가능성과 유지보수성 면에서 큰 장점을 제공합니다. 그러나 많은 Observer가 구독할 경우 성능에 영향을 미칠 수 있으므로 적절한 상황에서 활용하는 것이 중요합니다.
'Design Pattern' 카테고리의 다른 글
어댑터(Adapter) 패턴 (1) | 2024.10.12 |
---|---|
빌더(Builder) 패턴 (0) | 2024.10.10 |
Factory 패턴 및 추상 팩토리 패턴 (0) | 2024.10.02 |
디자인 패턴의 분류 (생성 패턴, 구조 패턴, 행위 패턴) (0) | 2024.10.01 |
SOLID 원칙: 객체 지향 설계의 5가지 핵심 원칙 (0) | 2024.10.01 |