한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고
자동으로 내용이 갱신되는 방식으로 일대다(One-To-Many) 의존성을 정의합니다.
옵저버 패턴에서는 크게 두 가지를 구현해야 한다.
하나는 상태를 가지고 있는 주제(Subject),
그리고 다른 하나는 그 주제에게서 상태를 전달받는 옵저버(Observer)가 있다.
흐름은 이렇다.
주제의 상태에 변화가 있음 -> 주제에게 등록되어 있는 옵저버들에게 변화된 상태가 전달됨
코드로 바로 알아보도록 하자.
먼저 상황을 가정해 보자.
우리는 군대 암구호 전달 시스템을 개발해야 한다.
public interface Subject {
// 옵저버 등록 메서드
public void registerObserver(Observer o);
// 옵저버 제거 메서드
public void removeObserver(Observer o);
// 상태의 변화가 있을 시 호출될 메서드
public void notifyObservers();
}
public interface Observer {
public void update();
}
여기 주제 인터페이스와 옵저버 인터페이스가 있다.
public class Army implements Subject {
// 등록된 옵저버들의 리스트
private List<Observer> observers;
// 문어
private String challenge;
// 답어
private String countersign;
public Army() {
observers = new ArrayList<Observer>();
}
// 옵저버 등록
public void registerObserver(Observer o) {
observers.add(o);
}
// 옵저버 제거
public void removeObserver(Observer o) {
observers.remove(o);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
// 암구호 변경 시 실행될 메서드
public void passwordChanged() {
notifyObservsers();
}
// 암구호 변경 메서드
public void setPassword(String challenge, String countersign) {
this.challenge = challenge;
this.countersign = countersign;
passwordChanged();
}
}
위에 주제 인터페이스를 구현한 Army 클래스가 있다.
Army 클래스는 암구호가 변경되면 옵저버들에게 바로 암구호를 전달하도록 한다.
public class P96K implements Observer {
// 문어
private String challenge;
// 답어
private String countersign;
private Army army;
// 생성 시 주제에 바로 등록이 된다.
public P96K(Army army) {
this.army = army;
army.registerObserver(this);
}
// 주제의 상태 변화가 있을 시 실행될 메서드
public void update() {
this.challenge = army.getChallenge;
this.countersign = army.getCountersign;
}
}
옵저버 인터페이스를 구현한 P96K 클래스가 있다.
P96K 클래스는 객체로 생성될 때 Army 클래스에 옵저버로서 등록이 된다.
그리고 Army 의 암구호가 변경이 있을 시 바로 전달을 받을 수 있다.
이렇게 옵저버 패턴을 사용하게 되면 어떤 주제의 상태에 변화가 있으면, 그 주제에 등록된 옵저버들은 자동으로 변경된 값을 전달받고 사용할 수 있게 된다.
P96K 클래스의 update() 메서드를 보자.
public void update() {
this.challenge = army.getChallenge;
this.countersign = army.getCountersign;
}
주제에서 값을 전달받는 것이 아니라, 값을 요청하고 있다.
이처럼 설계를 하게 되면 나중에 필요한 값만 골라서 받을 수 있는 이점이 있다.
실제로 옵저버 패턴은 많이 사용되고 있다.
대표적으로 자바의 GUI 프레임워크인 스윙에서 사용되고 있다.
그 외에도
에서 사용되고 있다.