디자인 패턴 - 02. 옵저버패턴

강준혁·2022년 9월 29일
0

디자인패턴

목록 보기
2/6

옵저버 패턴

옵저버 패턴은 한 객체의 상태가 바뀌면 그 객체에 의존하는 하나 이상의 객체들에게 변경된 상태가 전파되며 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다.

옵저버 패턴의 필요성

주식 정보를 구독하는 구독자들이 있다.

구독자들은 주식 정보의 상태에 따라 각기 다른 방식으로 대처를 해야한다.

class StockState {
  private String stateA;
  private String stateB;
  private String stateC;
  
  public void changeStates(String stateA, String stateB, String stateC) {
    this.stateA = stateA;
    this.stateB = stateB;
    this.stateC = stateC;
  }
}

interface Subscriptor {
  handle();
}

class SubscrpitorA implements Subscriptor {
  handle(StockState state) {
    //
  }
}

class SubscriptorB implements Subscriptor {
  handle(StockState state) {
    //
  }
}
Subscriptor subscriptor1 = new SubscriptorA();
Subscriptor subscriptor2 = new SubscriptorB();

// 새로운 주식 상태가 생성되면,
StockState state = new StockState('A', 'B', 'C');

// 각 구독자들에게 정보를 알려줘야 한다.

subscriptor1.handle(state);
subscriptor2.handle(state);

// 상태가 변경될 때마다 변경을 알려준다.
state.changeStates('D', 'E', 'F');

subscriptor1.handle(state);
subscriptor2.handle(state);

// 구독자가 추가되면 변경된 구독자에게도 변경사항을 전파해주어야 한다.
Subscriptor subscriptor3 = new SubscriptorB();
state.changeStates('D', 'E', 'F');

subscriptor1.handle(state);
subscriptor2.handle(state);
subscriptor3.handle(state);

이처럼 구현할 경우, 구독자가 늘어나는 변경에 유연하게 대처하지 못하는 문제가 발생한다.

옵저버 패턴의 적용

옵저버 패턴은 어떤 상태의 변화를 다수의 객체들에게 전달해야 하는 경우, 전파해야할 '주제' 와 주제의 변경에 의존할 '옵저버'의 인터페이스를 정의하고 '옵저버' 인터페이스를 구현한 객체들이 '주제' 객체에 등록만 하면 '주제' 객체는 변경이 일어날 때마다 등록된 옵저버 객체들에게 변경사항을 전파함으로서 변경에 유연하게 대처할 수 있도록 한다.

주제와 옵저버의 인터페이스를 정의한다.

public interface Subject {
  public void registerObserver(Observer o);
  public void removeObserver(Observer o);
  public void notifyToObservers();
}

public interface Observer {
  public void update(StockState state);
}

주식 상태 클래스가 Subject 인터페이스를 구현하도록 수정한다

class StockState implements {
  ...
  private List<Observer> observers = new ArrayList<Observer>();
  
  public void registerObserver(Observer o) {
    observers.add(o);
    o.update(this);
  }
  
  public void removeObserver(Observer o) {
    observers.remove(o);
  }
  
  public void notifyToObservers() {
    for (Observer o : observers) {
      observer.update(this);
    }
  }
  
  public void changeStates(String stateA, String stateB, String stateC) {
    this.stateA = stateA;
    this.stateB = stateB;
    this.stateC = stateC;
    notifyToObservers();
  }
}

구독자 클래스들이 Observer 인터페이스를 구현하도록 수정한다.

interface Subscriptor extends Observer {
  handle();
}

class SubscrpitorA implements Subscriptor {
  public void handle(StockState state) {
    //
  }
  
  public void update(StockState state) {
    handle(state);
  }
}

class SubscriptorB implements Subscriptor {
  public void handle(StockState state) {
    //
  }
  
  public void update(StockState state) {
    handle(state);
  }
}

이처럼 구현하게 되면 구독자들이 늘어나는 경우 객체에 구독자를 추가만 해주면 된다.

Subscriptor subscriptor1 = new SubscriptorA();
Subscriptor subscriptor2 = new SubscriptorB();

// 새로운 주식 상태가 생성되면,
StockState state = new StockState('A', 'B', 'C');

// 구독자들을 추가한다.
state.registerObserver(subscriptor1);
state.registerObserver(subscriptor2);

// 상태가 변경되는 경우에는 자동으로 구독자들에게 전파된다.
state.changeStates('D', 'E', 'F');

// 구독자가 추가되는 경우에도 추가적인 코드는 불필요하다.
Subscriptor subscriptor3 = new SubscriptorB();
state.registerObserver(subscriptor3);
profile
백엔드 개발자

0개의 댓글