해당 포스트는 "자바 객체지향 디자인 패턴", "JAVA 언어로 배우는 디자인 패턴 입문" 책의 내용을 요약한 것이다.



※옵저버(Observer) 패턴

: 한 객체의 상태가 바뀌면 그 객체에 의존/연결 되어 있는 다른 하나 또는 다수의 객체들한테 자동으로 이벤트가 전달되어 정보가 갱신되는 패턴이다. 예를 들면, 신문을 발행하는 신문사와 신문 정기 구독자의 관계, 동아리 회원과 회원들에게 매주 공지사항을 보내는 운영진들과의 관계 등 많이 있다.

 

- 옵저버 패턴 구현 방법 2가지

1. JDK에서 지원하는 Observable과 Observer API를 활용하는 방법

2. API를 활용하지 않고 직접 구현하는 방법

 

ex) 해당 예제는 http://hyeonstorage.tistory.com에서 가져왔다.

해당 예제는 온도, 습도, 압력 데이터가 갱신되어 WeatherData 클래스로 데이터가 전송되면 WeatherData클래스는 자신과 연결되어 있는 다수의 Display 객체에 갱신 정보가 전송되어 자신의 디스플레이를 업데이트하는 예제이다.

 

1. 첫 번째 방법인 JDK API를 이용한 방법

 

<Observable>

import java.util.Observable;

public class WeatherData extends Observable {
	private float temperature;
	private float humidity;
	private float pressure;
	
	public WeatherData(){}
	
	/**
	 *  새로운 데이터를 전달받아 갱신하고 새로운 데이터가 왔다는 것을 연결된 객체들에게 알린다. 
	 */
	public void setData(float temperature, float humidity, float pressure){
		this.temperature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		dataChanged();
	}

	
	/**
	 * setChanged() : Observable 클래스 내부 changed 변수를 true로 만들어준다.
	 * 					changed 변수가 true여야 연결된 객체(옵저버)에 신규 데이터가 전달된다.
	 * notifyObservers() : 등록된 옵저버에게 데이터를 전송한다. 옵저버에서는 update() 함수가 호출된다. 
	 */
	public void dataChanged() {
		super.setChanged();  
		super.notifyObservers();
	}



	public float getTemperature() {
		return temperature;
	}



	public float getHumidity() {
		return humidity;
	}



	public float getPressure() {
		return pressure;
	}
}

<Observer>

import java.util.Observable;
import java.util.Observer;

public interface Display {
	public void display();
}

class KoreanDisplay implements Observer, Display{

	private Observable observable; // 등록될 Observable
	
	private float temperature;
	private float humidity;
	private float pressure;
	
	public KoreanDisplay(Observable observable) {
		this.observable = observable;
		observable.addObserver(this); //this(KoreaDisplay)를 옵저버로 등록
	}
	
	@Override
	public void display() {
		System.out.println("온도 : "+temperature);
		System.out.println("습도 : "+humidity);
		System.out.println("압력 : "+pressure);
	}

	
	/* 
	 * Observable에서 notifyObservers()를 호출할 시 해당 메소드가 호출되어 옵저버의 데이터가 갱신
	 */
	@Override
	public void update(Observable arg0, Object arg1) {
		if(arg0 instanceof WeatherData){
			WeatherData weatherData = (WeatherData)arg0;
			this.temperature = weatherData.getTemperature();
			this.humidity = weatherData.getHumidity();
			this.pressure = weatherData.getPressure();
			display();
		}
	}
}

class EnglishDisplay implements Observer, Display{

	private Observable observable; // 등록될 Observable
	
	private float temperature;
	private float humidity;
	private float pressure;
	
	public EnglishDisplay(Observable observable) {
		this.observable = observable;
		observable.addObserver(this); //this(EnglishDisplay)를 옵저버로 등록
	}
	
	@Override
	public void display() {
		System.out.println("temperature : "+temperature);
		System.out.println("humidity : "+humidity);
		System.out.println("pressure : "+pressure);
	}

	
	/* 
	 * Observable에서 notifyObservers()를 호출할 시 해당 메소드가 호출되어 옵저버의 데이터가 갱신
	 */
	@Override
	public void update(Observable arg0, Object arg1) {
		if(arg0 instanceof WeatherData){
			WeatherData weatherData = (WeatherData)arg0;
			this.temperature = weatherData.getTemperature();
			this.humidity = weatherData.getHumidity();
			this.pressure = weatherData.getPressure();
			display();
		}
	}
}
public class Main {
	public static void main(String[] args) {
		WeatherData weatherData = new WeatherData();
		Display kd = new KoreanDisplay(weatherData);
		Display ed = new EnglishDisplay(weatherData);
		
		weatherData.setData(20, 50, 10);
		System.out.println("30분 후");
		weatherData.setData(30, 40, 5);
	}
}

<결과>

예제에서 보다시피 weatherData(Observable)의 setData() 메서드를 통해서 Observer들의 데이터를 갱신한다. 하지만 Observable이 클래스이기 때문에 다중 상속이 불가능한 자바에서 사용성이 많이 떨어진다. 또한, Observable 클래스 핵심 메서드(setChanged) 같은 것들이 protected로 선언되어 있어 외부에서 호출이 불가능하다는 단점이 있다. 이에 대한 해결책으로 두 번째 방법인 직접 구현하는 방법이 있다. 그건 다음 포스트에 작성할 예정이다.

'자바 > 디자인패턴' 카테고리의 다른 글

퍼사드 패턴  (0) 2017.06.08
프로토타입 패턴  (0) 2017.06.08
컴퍼지트 패턴  (0) 2017.06.07
데코레이터(Decorator) 패턴  (0) 2017.06.06
옵저버(Observer) 패턴(2) - 직접 구현  (0) 2017.06.06

+ Recent posts