옵저버 패턴(Observer Pattern) 동작 방식

옵저버 패턴(Observer Pattern)에서는 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의합니다.

code reference

  1. 주제 객체에 옵저버를 옵저버 목록에 추가합니다.
  2. 주제 객체의 값이 바뀌면 등록된 옵저버들에게 연락을 합니다.
  3. 데이터를 받을 필요가 없는 옵저버들은 옵저버 목록에서 삭제합니다.

느슨한 결합(Loose coupling)의 위력

옵저버 패턴에서는 주제와 옵저버가 느슨하게 결합되어 있는 객체 디자인을 제공합니다.

  • 주제가 옵저버에 대해서 아는 것은 옵저버가 특정 인터페이스를(Observer Interface)를 구현한다는 것 뿐입니다.
  • 옵저버는 언제든지 새로 추가할 수 있습니다.
  • 새로운 형식의 옵저버를 추가하려고 할 때도 주제를 전혀 변경할 필요가 없습니다.
  • 주제와 옵저버는 서로 독립적으로 재사용할 수 있습니다.
  • 주제나 옵저버나 바뀌더라도 서로한테 영향을 미치ㅈ는 않습니다.

Design Principal 4.
서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.

자바 내장 옵저버 패턴(Observer Pattern) 사용하기

code reference

자바 내장 옵저버 패턴을 사용하면 푸시 방식으로 갱신할 수도 있고, 풀 방식으로도 갱신할 수 있다는 장점이 있습니다.

  • 객체가 옵저버(Observer)가 되는 방법

    Observer 인터페이스를 구현하고 addObservers를 호출합니다.

    import java.util.Observable;
    import java.util.Observer;
    
    public class CurrentConditionsDisplay implements Observer, DisplayElement {
        Observable observable;
        private float temperature;
        private float humidity;
    
        public CurrentConditionsDisplay(Observable observable) {
            this.observable = observable;
            observable.addObserver(this);
        }
    
        @Override
        public void update(Observable o, Object arg) {
            if (o instanceof WeatherData) {
                WeatherData weatherData = (WeatherData) o;
                this.temperature = ((WeatherData) o).getTemperature();
                this.humidity = ((WeatherData) o).getHumidity();
                display();
            }
        }
    
        @Override
        public void display() {
            System.out.println("Current condition : " + temperature + "F degress and " + humidity + "% humidity");
        }
    }
  • Observable에서 연락을 돌리는 방법

    1. setChanged() 메소드를 호출해서 객체의 상태가 바뀌었다는 것을 알립니다.

    2. 그 다음으로 notifyObservers() 또는 notifyObservers(Object args) 를 호출합니다.

      import java.util.Observable;
      
      public class WeatherData extends Observable {
          private float temperature;
          private float humidity;
          private float pressure;
      
          public WeatherData() {
          }
      
          public void measurementsChanged() {
              setChanged();
              notifyObservers();
          }
      
          public void setMeasurements(float temperature, float humidity, float pressure) {
              this.temperature = temperature;
              this.humidity = humidity;
              this.pressure = pressure;
              measurementsChanged();
          }
      
          public float getTemperature() {
              return temperature;
          }
      
          public float getHumidity() {
              return humidity;
          }
      
          public float getPressure() {
              return humidity;
          }
      }
  • 옵저버(Observer)가 연락을 받는 방법

    update(Observable o, Object args) 를 통해 메소드를 구현합니다.

Observable에 setChanged()의 사용법

데이터가 수없이 변화할 때에 모든 변화에 대해서 옵저버(Observer)들에게 호출하지 않고 특정 조건일 때에만 호출을 할 수 있도록 연락을 최적화해주는 용도로 사용하게 됩니다.

Java Obervable을 사용했을 경우의 특징

옵저버(Observer)들에게 연락을 순차적으로 돌리지 않습니다.

java.util.Observable의 단점

  1. interface가 아니고 class이기 때문에 재사용성에 있어 제약조건이 발생합니다.

  2. Observable 인터페이스라는 것이 엇기 때문에 Observer API하고 잘 맞는 클래스를 직접 구현하는 것이 불가능합니다.

  3. Observable 클래스의 핵심 메소드를 외부에서 호출할 수 없습니다.

    Observable의 subclass에서만 setter를 호출할 수 있기 때문에 값 변경이 불가합니다.

    이는 상속보다 구성 이라는 디자인 원칙에도 위배됩니다.

Java의 Observer & Observable은 Java9부터 deprecated 되었으니 참고 부탁드립니다.
Java SE 9 문서의 Observable

Deprecated.
This class and the Observer interface have been deprecated. The event model supported by Observer and Observable is quite limited, the order of notifications delivered by Observable is unspecified, and state changes are not in one-for-one correspondence with notifications. For a richer event model, consider using the java.beans package. For reliable and ordered messaging among threads, consider using one of the concurrent data structures in the java.util.concurrent package. For reactive streams style programming, see the Flow API.

profile
재밌는 것만 하고 싶어 ʕ•ﻌ•ʔ

0개의 댓글