옵저버 패턴은 객체 간의 일대다 의존 관계를 정의하는 디자인 패턴 중 하나입니다. 이 패턴에서, 한 객체가 변경되면 그 객체에 의존하는 다른 객체들에게 알림이 전달되어 자동으로 업데이트 됩니다. 이를 통해 객체 간의 결합도를 줄이고, 유연한 설계를 가능하게 합니다.
1. 구성요소
- Subject: 변경 사항이 발생하는 객체
- Observer: 변경 사항을 알림 받는 객체
- ConcreteSubject: Subject의 구현체
- ConcreteObserver: Observer의 구현체
2. 예제 코드
파이썬으로 구현한 예제 코드는 다음과 같습니다.
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
if observer not in self._observers:
self._observers.append(observer)
def detach(self, observer):
try:
self._observers.remove(observer)
except ValueError:
pass
def notify(self, message):
for observer in self._observers:
observer.update(message)
class Observer:
def update(self, message):
raise NotImplementedError()
class ConcreteSubject(Subject):
def __init__(self):
super().__init__()
self._state = None
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify(value)
class ConcreteObserver(Observer):
def __init__(self, name):
self._name = name
def update(self, message):
print(f"{self._name} received message: {message}")
if __name__ == "__main__":
subject = ConcreteSubject()
observer1 = ConcreteObserver("Observer 1")
observer2 = ConcreteObserver("Observer 2")
subject.attach(observer1)
subject.attach(observer2)
subject.state = "new state"
위 코드에서 Subject 클래스는 attach, detach, notify 메서드를 제공합니다. attach 메서드는 옵저버를 추가하는 메서드이며, detach 메서드는 옵저버를 제거하는 메서드입니다. notify 메서드는 Subject의 상태가 변경될 때 호출되며, 등록된 모든 옵저버들에게 상태 변경을 알리는 역할을 합니다.
Observer 클래스는 update 메서드를 제공합니다. 이 메서드는 Subject에서 알림을 받았을 때 호출되며, 구체적인 옵저버들은 이 메서드를 구현하여 자신의 특정 로직을 수행하게 됩니다.
ConcreteSubject 클래스는 Subject를 구현한 구체적인 클래스입니다. 이 클래스는 상태를 저장하고, 상태가 변경될 때마다 notify 메서드를 호출하여 옵저버들에게 알립니다.
ConcreteObserver 클래스는 update 메서드를 구현하여 옵저버가 상태 변경을 수신할 때마다 호출되는 로직을 정의합니다. 위 코드에서는 update 메서드에서 메시지를 출력하는 것으로 구현되어 있습니다.
3. 사용 사례
옵저버 패턴은 다양한 곳에서 사용됩니다. 예를 들어, GUI 프로그래밍에서는 버튼이나 텍스트 박스 등과 같은 위젯이 Subject 역할을 하고, 이 위젯을 관찰하는 다른 위젯이 Observer 역할을 합니다. 이때, Subject 위젯의 상태가 변경될 때마다 Observer 위젯에게 알림을 전달하여 업데이트를 수행하도록 할 수 있습니다.
또한, 데이터베이스 시스템에서도 옵저버 패턴이 활용됩니다. 예를 들어, 데이터베이스 테이블의 특정 레코드가 변경되었을 때, 이를 관찰하는 다른 프로세스나 서비스에 변경 사항을 알리기 위해 옵저버 패턴을 사용할 수 있습니다.
옵저버 패턴은 객체 간의 결합도를 낮추고, 유연한 설계를 가능하게 해줍니다. 따라서, 객체 지향 프로그래밍에서는 옵저버 패턴을 활용하여 유연하고 확장 가능한 시스템을 구현하는 것이 중요합니다.
4. 장점
- 유연성: 옵저버 패턴은 객체 간의 결합도를 낮추고, 유연한 설계를 가능하게 합니다. Subject 클래스와 Observer 클래스는 서로 독립적이며, 서로의 존재를 알 필요가 없습니다. 이는 시스템의 유연성을 높이고, 변경이 용이하게 만들어줍니다.
- 확장성: 옵저버 패턴은 새로운 Observer 클래스를 추가하는 것이 매우 쉽습니다. 기존의 Subject 클래스 코드를 수정하지 않고, 새로운 Observer 클래스를 추가하여 Subject 클래스의 동작을 확장할 수 있습니다.
- 분리된 역할: 옵저버 패턴은 Subject 클래스와 Observer 클래스 각각의 역할을 분리하여 구현할 수 있습니다. 이는 코드의 가독성과 유지보수성을 향상시켜줍니다.
5. 단점
- 성능 문제: 옵저버 패턴을 구현할 때, Subject 클래스에서 notify 메서드를 호출하여 Observer 클래스들에게 상태 변경을 알리기 때문에, 이 과정에서 성능 문제가 발생할 수 있습니다. 만약 옵저버가 많아지거나, 업데이트 로직이 복잡해지면, 성능에 영향을 미칠 수 있습니다.
- 오버헤드: 옵저버 패턴은 객체 간의 상호작용을 위해 많은 객체를 생성해야 하기 때문에, 메모리와 처리 시간에 오버헤드가 발생할 수 있습니다.
- 구현의 복잡성: 옵저버 패턴을 구현하는 것은 비교적 어렵습니다. Subject 클래스와 Observer 클래스 사이의 상호작용을 올바르게 구현하기 위해서는 상당한 노력과 경험이 필요할 수 있습니다.
'설계' 카테고리의 다른 글
[디자인 패턴] 스트래티지 패턴 (Strategy Pattern) - python 예제 코드 (0) | 2023.03.11 |
---|---|
[디자인 패턴] 스테이트 패턴 (State Pattern) - python 예제 코드 (0) | 2023.03.10 |
[디자인 패턴] 메멘토 패턴 (Memento Pattern) - python 예제 코드 (0) | 2023.03.10 |
[디자인 패턴] 중재자 패턴 (Mediator Pattern) - python 예제 코드 (0) | 2023.03.10 |
[디자인 패턴] 반복자 패턴 (Iterator Pattern) - python 예제 코드 (0) | 2023.03.09 |