
옵저버 패턴이란
Observer의 사전적 의미에는 관측자, 입회인, 감시자 등이 있다. 시스템을 설계하다 보면 한쪽의 상태가 변경되면 관련된 객체들이 즉각 알아야하거나, 반대로 알려줘야 하는 상황이 온다.
Observer Pattern은 관련된 객체들의 명단을 가지고 있다가 특정정보 변경/발행 시 객체들의 명단에 알람을 전달한다.
다이어그램

발행한 값을 반영하는 update() 메소드의 기능을 정의해놓은 인터페이스 Observer와 인터페이스를 구현한 ConcreteObserver 클래스가 있다.
Publisher 클래스는 Observer 인터페이스를 구현하는 클래스들의 List를 가지며 subscribe(), unsubscribe()로 추가, 제거할 수있다. 값을 subscriber들에게 전달하고 싶다면 notifyObserver() 함수를 통해 List에 저장된 Observer 구현클래스들에게 일률적으로 update() 함수를 호출한다
예
특정 클래스에서 값이 변경될때 마다 연관된 모든 클래스가 알아야 하는 상황이 있다.
간단한 예로 컴퓨터 볼륨에서 음량을 100%에서 50%로 조정하면 Progress Bar UI와 오디오 인터페이스 내부 어딘가에서 음량을 반으로 줄여야 한다.
가장 간단한 방법으로 UI와 오디오API에서 계속적으로 값의 변화를 관찰하는 Polling을 사용할 수도 있지만 너무나도 비효율적이다.
Event-Driven 방식을 이용해서 사용할 수도 있겠지만 복잡하니까 넘어간다.
public class VolumeUI {
public void showVolume(double value);
}
public class Audio {
public void setVolume(double value);
}
...
while(true) {
if (isValueChanged()) {
VolumeUI.showVolume(value);
Audio.setVolume(value);
}
}
// 너무나도 비효율적이다..
여기서 볼륨을 조정하는 사용자(혹은 커널)는 발행자(Observable)이며, UI와 오디오는 구독자(Observer)다.
발행시 취할 액션을 정의한 간단한 인터페이스를 만들고 구독자들은 인터페이스를 구현한다. 발행자는 구독자들을 저장한 뒤 인터페이스에 맞게 발행시에 취할 액션을 호출하면 된다
public interface VolumeObserver {
void volumeChanged(double value);
}
public class VolumeUI implements VolumeObserver {
@Override
public void volumeChanged(double value) {
this.showVolume(value);
}
}
public class Audio implements VolumeObserver {
@Override
public void volumeChanged(double value) {
this.setVolume(value);
}
}
public class Kernel {
List<VolumeObserver> lists;
...
public void changeVolume() {
for (VolumeObserver list : lists) {
list.volumeChanged(value);
}
}
}
위 Kernel 클래스는 등록된 구독자 컬렉션을 순회하면서 인터페이스의 메소드를 호출하기만 해도, 구독자들은 인터페이스를 구현하였기 때문에 적절한 액션을 취할 수 있다.
'디자인패턴' 카테고리의 다른 글
| 어댑터 패턴 (Adapter Pattern) (0) | 2022.11.18 |
|---|---|
| 커맨드 패턴 (Command Patter) (0) | 2022.11.17 |
| 데코레이터 패턴(Decorator Pattern) (0) | 2022.10.21 |
| 전략 패턴 (Strategy Pattern) (0) | 2022.09.15 |
