옵저버패턴

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


옵저버 패턴 조건

객체간의 결합도는 높아질수록 유지보수가 힘들기 때문에 일단 객체간의 결합도는 낮추는게 일반적이다.

옵저버를 언제든지 추가하려고 할때도 주제를 전혀 변경할 필요가 없다.


예제

가상 모니터링 애플리케이션을 구현해보자.

이 시스템은 다음과 같이 3개의 요소로 어루어져 있고(가상 스테이션, 날씨 데이터, 디스플레이 장비) Weather Data를 통해서 3개 혹은 그 이상 디스플레이 장비에 데이터를 보여주게 된다.





분석

1. 옵저버 패턴의 정의를 떠올리면 one-to-many 관계이므로 one = Weather Data , many = Display 장치가 된다

2. Weather Data 객체를 주제객체로 하고 Display 장치에서 옵저버로 하는 경우 Display 애서 자기가 원하는 정보를

    얻기위해  Weather Data 객체에 등록할수 있는 registerObserver()메소드가 필요하다.

3. 모든 Display 장치는 항목이 다를 수 있다. 그러므로 바로 이 부분이 공통 인터페이스를 이용해서 처리가 가능함

   각 장치마다 구성 요소의 형식이 달라도 똑같은 인터페이스를 구현해야만 Weather Data 객체에서 기상 스테이션으로 측정값을 보낼      수 있다.

4. 즉 모든 디스플레이 장치는 Weather Data 에서 호출할 수 있는 update()메소드가 필요하다. 그리고 이 update() 메소드는 모든 장치들    이 구현하는 공통 인터페이스에 정의 되야 한다.



옵저버 패턴 적용

UML 확인하고 코딩하기!




Observer .java


Subject .java

DisplayElement .java

WeatherData.java

CurrentConditionsDisplay.java

Main .java


display는 하나만 구현함!

동작 시나리오

① WeatherStation에서는 온도, 습도, 기압 정보를 수집한다.

② WeatherStation에서 주기적으로 (30분에 한번식) 현재 데이터(온도,습도,기압)을 WeatherData에 던져 준다.

③ WeatherData는 새로운 데이터를 받으면, Observable에 Observer로 등록되어 있는, 현재상태 출력장비(CurrentConditionDisplay)와 기압변동 출력장비(ForecastDisplay)에 새로운 데이터를 전달한다.

④ 현재상태 출력장비와 기압변동 출력장비는 새로운 데이터(온도, 습도, 기압)을 각자의 활용 방법에 따라 화면에 출력한다.

⑤ WeatehrStation에서 다시 새로운 데이터를 던져준다. 

⑥ ①~④ 번이 반복되며, 주기적으로 현재상태 출력장비와 기압변동 출력장비는 새로운 데이터를 출력한다.


java에서 제공하는 옵저버 패턴 적용




WeatherData.java


CurrentConditionsDisplay .java

Main.java

 java.util.Observable.class  확인


java.util.Observable.class


소스코드 보기


- addObserver(Observer o) : 옵저버를 등록한다. 이후에 들어오는 데이터는 등록된 옵저버에 전달된다.

- deleteObserver(Observer o) : 옵저버를 제거한다. 이후에 들어오는 데이터는 해당 옵저버에 전달되지 않는다.

- notifyObservers(), notifyObservers(Object arg) : 새로운 데이터가 들어오면 등록된 옵저버에 새로운 데이터와, 파라미터를 전달한다.

- deleteObservers() : 등록된 모든 옵저버를 제거한다. 이후에 들어오는 데이터는 전달되지 않는다.

- setChanged() : 신규 데이터가 들어오면, changed 값을 true로 변경, changed 변수가 true 일때만 데이터가 옵저버에 전달된다.

- clearChanged() : changed 값을 false 로 변경한다. 신규 데이터를 옵저버에 전달이 완료되면 clearChanged()를 호출한다.

- hasChanged() : 현재 changed 의 값을 반환한다.

- countObservers() : 현재 등록되어있는 옵저버의 수를 반환한다.



자바의 내장된 옵저버 패턴 이용 (Observable)


- setMeasurements(float temperature, float humidity, float pressure) : 기상스테이션에서 온도, 습도, 기압 측정값을 전달할때 호출한다. 파라미터로 받은 데이터를 갱신하고 measuermentChanged()를 호출한다.

- measurementsChanged() : 옵저버에 전달할 새로운 데이터가 있다고 알리고(setChanged()), 등록된 옵저버에 데이터를 전달한다.(notifyObservers())  (setChanged()와 notifyObservers()는 Observable에서 상속받은 함수이다.)


보는것과 같이 WeatherData.java는 Observable 을 상속하였다. 따라서 Observable의 함수를 사용하여, Observer들에게 데이터를 전달할 수 있다.


15열의 setMeasurements() 함수와 24열의 measurementsChanged() 함수를 보자

기상스테이션(WeatherStation.java)는 주기적으로 데이터(온도,습도,기압)값을 WeatherData의 setMeasurements() 함수를 사용하여 전달한다.

setMeasurements()는 전달받은 데이터를 각 변수에 갱신한 뒤, measurementsChanged() 함수를 호출한다.


measuremensChanged() 함수는 Observer에게 데이터를 전달한다.

먼저 setChanaged() 함수를 호출하여, 전달할 새로운 데이터가 있음을 설정한다. 그리고 notifyObservers() 함수를 호출하여, 갱신한 새로운 데이터를 각 등록된 옵저버에게 전달한다.


정말 간단하다. Observable 을 상속한뒤, 옵저버들에게 데이터를 전달할 때, setChanged()와 notifyObservers()를 순차적으로 호출하면 된다. 그러면 데이터가 등록된 옵저버들에게 전달되는 것이다.







'JAVA > Design patten' 카테고리의 다른 글

factory method pattern  (0) 2019.04.27
singleton-pattern  (0) 2019.04.27
Decorator Pattern (데코레이터 패턴)  (0) 2015.09.03
Posted by 양승아
: