옵저버패턴(Observer Pattern) 에 대해 알아보겠다.
옵저버 패턴은 Subject에서 각 객체(옵저버)들을 조절하며 데이터를 변경하거나 옵저버들을 추가 또는 제거등을 할 수 있는 기능이다.
00. Subject 인터페이스를 만들고 등록/ 제거/ 알림 메소드를 만든다.
01. Observer 인터페이스를 만든다. 모든 옵저버클래스에서 상속받아서 정보를 업데이트 시킬 중요한 인터페이스이다.
02. DisplayElement 인터페이스를 만든다. 화면에 보여줄 메소드를 나중에 상속받아서 작성 해 줄 것이다.
03. WeatherData라는 클래스를 만들고 Subject를 상속받고, 내용들을 작성 해 준다.
04. CurrentConditionDisplay 클래스를 만들고 observer와 displayElement를 다중상속 받아서 내용을 만들어준다.
05. Main클래스에 객체를 생성하고 값을 변경해보자.
06. 정상작동됨을 확인할 수 있다.
************** Subject Interface **************
package kr.or.komca.smin;
public interface Subject {
/* Observer를 인자로 받아서 등록 하는 역할 */
public void registerObserver(Observer o);
/* Observer를 인자로 받아서 제거 하는 역할 */
public void removeObserver(Observer o);
/* 주제 객체의 상태가 변병되었을 때 모든 옵저버들에게 알리기 위해 호출되는 메소드 */
public void notifyObservers();
}
************** Observer Interface **************
package kr.or.komca.smin;
public interface Observer {
/* 모든 옵저버 클래스에서 구현되어야 한다.
* 따라서 모든 옵저버에서 아래의 update메소드를 구현해야 한다.
* */
public void update (float temp, float humidity, float pressure);
}
************** DisplayElement Interface **************
package kr.or.komca.smin;
public interface DisplayElement {
/*
* 디스플레이 항목을 화면에 표시해야하는 경우 이 메소드 사용
* */
public void display();
}
**************CurrentConditionDisplay Class **************
package kr.or.komca.smin;
public class CurrentConditionsDisplay implements Observer, DisplayElement{
/*
* Observer ; WeatherData 객체로부터 변경사항을 받기위해 다중상속(implement) -> update() 必
* DisplayElement ; API 구조상 모든 디스플레이 항목에서 DisplayElement를 구현해야 하기 때문에 다중상속(implement) -> display() 必
*
* */
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData){
// Constructor에 객체가 전달됨.
// 이 객체를 써서 디스플레이를 옵저버로 등록함
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
// update가 호출 되어 변수로 저장되고 마지막 라인에서 display() 호출
this.temperature = temperature;
this.humidity = humidity;
display();
}
@Override
public void display() {
// 변수에 저장된 값을 나타내어 준다.
System.out.println("Current conditions : " + temperature + " F degree and " + humidity + " % humidity");
}
}
************** WeatherData Class **************
package kr.or.komca.smin;
import java.util.ArrayList;
public class WeatherData implements Subject{
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
//WeatherData()를 객체를 생성하면 리스트를 만든다.
observers = new ArrayList();
}
@Override
public void registerObserver(Observer o){
// 옵저버가 등록하면 리스트 맨뒤에 추가 됨
observers.add(o);
}
@Override
public void removeObserver(Observer o){
// 옵저버가 탈퇴를 신청하면 리스트에서 제거
int i = observers.indexOf(o);
if (i >= 0){
observers.remove(i);
}// if
}
public void notifyObservers(){
// 상태에 대해 모든 옵저버들에게 알려주는 부분
// 따라서, update해줘야함.
for(int i = 0 ; i <= observers.size() -1 ; i++){
Observer observer = (Observer)observers.get(i);
observer.update(temperature, humidity, pressure);
}//for
}
public void measurementsChanged(){
// WeatherStation으로 부터 갱신된 측정치를 받으면 옵저버들에게 update로 알림.
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure){
// 값들을 지정해주는 메소드
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//기타 메소드s
}//MAIN
************** WeatherStation Class **************
package kr.or.komca.smin;
public class WeatherStation {
public static void main(String[] args) {
// 작동을 데이터 값이 필요한 WeatherData객체생성
WeatherData weatherData = new WeatherData();
// WeatherData 객체의 값을 받기위해 CurrentConditionsDisplay에 지정한 Constructor객체를 생성
new CurrentConditionsDisplay(weatherData);
// 값을 변경해 보자.
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}