객체의 상태가 바뀌면 객체에 의존하는 다른 객체들에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one to many)의존성을 정의 한다.

 

일대다의 관계는 주제(Subject) 옵저버(Observer)’ 의해 정의된다. 옵저버 패턴을 구현하는 방법에는 여러가지 방법이 있지만, 대부분 주제(Subject)인터페이스와 옵저버(Observer)인터페이스가 들어있는 클래스 디자인을 바탕으로 한다.

 

 

위와 같은 설계(Observer 패턴) 객체간의 느슨한 결합(Loose Coupling) 디자인을 제공한다. 주제나 옵저버가 변경이 되더라도 서로에게 영향을 미치지 않는다.

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

 

아래는 기상 시스템을 설계하기 위해 WeatherData 주제로하고 여러가지 Display장비들이 WeatherData Observer 참여하여 WetherData로부터 변경된 기상정보를 통보 받을 것이다.

 

 

 

 

아래는 기상시스템의 설계를 Observer 패턴으로 설계한 예이다.

 

 

 

주제 인터페이스

 

package headfirst.observer.weather;

 

public interface Subject {

       public void registerObserver(Observer o);

       public void removeObserver(Observer o);

       public void notifyObservers();

}

 

 

 

옵저버 인터페이스

 

package headfirst.observer.weather;

 

public interface Observer {

       public void update(float temp, float humidity, float pressure);

}

 

 

 

주제

 

package headfirst.observer.weather;

 

import java.util.ArrayList;

 

public class WeatherData implements Subject {

       private ArrayList observers;

       private float temperature;

       private float humidity;

       private float pressure;

 

       public WeatherData() {

              observers = new ArrayList();

       }

 

       /* (non-Javadoc)

        * @see headfirst.observer.weather.Subject#registerObserver(headfirst.observer.weather.Observer)

        */

       @Override

       public void registerObserver(Observer o) {

              observers.add(o);

       }

 

       /* (non-Javadoc)

        * @see headfirst.observer.weather.Subject#removeObserver(headfirst.observer.weather.Observer)

        */

       @Override

       public void removeObserver(Observer o) {

              int i = observers.indexOf(o);

              if (i >= 0) {

                     observers.remove(i);

              }

       }

 

       /* (non-Javadoc)

        * @see headfirst.observer.weather.Subject#notifyObservers()

        */

       @Override

       public void notifyObservers() {

              for (int i = 0; i < observers.size(); i++) {

                     Observer observer = (Observer) observers.get(i);

                     observer.update(temperature, humidity, pressure);

              }

       }

 

       public void measurementsChanged() {

              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 pressure;

       }

}

 

 

 

옵저버 많은 옵저버들이 존재할 있다.

 

package headfirst.observer.weather;

 

public class CurrentConditionsDisplay implements Observer, DisplayElement {

       private float temperature;

       private float humidity;

       private Subject weatherData;

 

       // 생성자에 Observer객체(WeatherData)의 레퍼런스를 생성자로 전달한다.

       public CurrentConditionsDisplay(Subject weatherData) {

              this.weatherData = weatherData;

              weatherData.registerObserver(this);

       }

 

       public void update(float temperature, float humidity, float pressure) {

              this.temperature = temperature;

              this.humidity = humidity;

              display();

       }

 

       /* (non-Javadoc)

        * @see headfirst.observer.weather.DisplayElement#display()

        */

       public void display() {

              System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");

       }

}

 

 

 

테스트클래스 – 기상스테이션.

 

package headfirst.observer.weather;

 

import java.util.*;

 

public class WeatherStation {

 

public static void main(String[] args) {

        WeatherData weatherData = new WeatherData();

       

        // 다음 코드에서 weatherData 객체를 Observer객체의 생성자로 전달하므로써

        // Subject객체가 되는 weatherData에 자신을 등록할수 있도록 한다.

        // 즉 내부에서는 생성자로부터 전달된 weatherData객체를 이용하여

        // weatherData.registerObserver(this);의 코드를 이용하여 자신을 등록한다.

        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);

        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);

        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);

 

        // setMeasurements()를 호출하면 등록된 Observer들의 update 메소드를 차례대로 호출하여 변경사항을 알린다.

        weatherData.setMeasurements(80, 65, 30.4f);

        weatherData.setMeasurements(82, 70, 29.2f);

        weatherData.setMeasurements(78, 90, 29.2f);

    }

}

 

 

 

java.util.Observable 이용한 옵저버 패턴

자바의java.util.Observable 이용해서 주제와 java.util.Observer 이용하여 옵저버 클래스를 구현 수있다.

참조 : http://stevenjsmin.tistory.com/36

 

 

CurrentConditionsDisplay.java

DisplayElement.java

ForecastDisplay.java

HeatIndexDisplay.java

Observer.java

StatisticsDisplay.java

Subject.java

WeatherData.java

WeatherStation.java

WeatherStationHeatIndex.java

'Java Design Pattern' 카테고리의 다른 글

Factory 패턴  (0) 2013.02.20
Decorator 패턴  (0) 2013.02.20
Strategy 패턴 - 알고리즘을 사용하는 클라이언트와 독립적으로 구현  (0) 2013.02.20
Facade 패턴  (0) 2013.02.19
Adapter 패턴  (0) 2013.02.19
Posted by Steven J.S Min
,