ios dev kangwook.

02. Observer Pattern 본문

Design Pattern

02. Observer Pattern

kangwook 2022. 3. 13. 00:30
객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 알림을 주도록 하는 디자인 패턴

Observer Pattern

Observer Pattern은 객체 간의 일대다(one to many) 의존성을 정의하여 하나의 객체가 상태를 변경할 때 모든 종속자에게 자동으로 알림과 업데이트를 제공한다.

 

  • Subject : Observer를 알고 있는 주체. Observer를 등록하고 제거하는 데 필요한 인터페이스를 정의
  • Observer : Subject에서 변화했다고 알렸을 때 갱신해야하는데 필요한 인터페이스를 정의
  • ConcreteSubject : 객체(Observer)에게 알려줘야할 상태를 지정, notify 해야할 함수를 만들도록 함
  • ConcreteObserver : update를 했을 경우 행동할 로직 작성

 


 

  • Loose Coupling(느슨한 결합) 
    • 주체와 옵저버가 느슨하게 결합
    • 옵저버는 언제든 추가 / 제거 가능
    • 새로운 형식의 옵저버를 추가해도 주체를 변경할 필요가 없음
    • 주체와 옵저버는 서로 독립적으로 재사용 가능
    • 주체나 옵저버가 바뀌더라도 서로에게 영향을 미치지 않음

Observer Pattern 예제

  • Weather-O-Rama 사의 기상 모니터링 애플리케이션
  • WeatherData 객체를 사용해 현재조건, 기상통계, 기상예측 세 항목을 디스플레이에 갱신해 보여주는 애플리케이션
  • 기상 정보를 수집하는 기상 스테이션
  • WeatherData 객체
  • 기상조건을 보여주는 디스플레이로 이루어짐

  • update 메서드의 temp, humidity, pressure은 Subject로부터 상태가 날씨 측정값이 바뀌었을경우 받아오는 상태 값
  • Subject의 상태가 바뀌었을 경우에 notify를 통해 모든 옵저버들에게 알림
public interface Subject {
	// 옵저버 등록(추가), 제거, 호출
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObserver(Observer o);
}

public interface Observer {
	// 기상정보가 변경되었을 때 옵저버에게 전달되는 값
	public void update(float temp, float humidity, float pressure);
}

public interface DisplayElement {
	// 화면 표시
	public void display();
}

 

  • Subject를 구현한 WeatherData

 

 

public class WeatherData implements Subject {
	private ArrayList<Observer> observers; // 옵저버 객체 저장
	private float temperature;
	private float humidity;
	private float pressure;

	public WeatherData() {
		observers = new ArrayList<Observer>();
	}

	public void registerObserver(Observer o) {
		observers.add(o);
	}

	public void removeObserver(Observer o) {
		int i = observers.indexOf(o);
		if (i >= 0) {
			observers.remove(i);
		}
	}

	public void notifyobservers() {
		for (Observer observer : observers) {
			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();
	}

	...
}
  • 변경사항을 받기 위한 Observer, 디스플레이 항목 구현
public class CurrentConditionsDisplay implements Observer, DisplayElement {
	private float temperature;
	private float humidity;
	private Subject weatherData;
	
	// 생성자에 주체 객체 전달, 옵저버로 등록
	public CurrentCoditionsDisplay(Subject weatherData) {
		this.weatherData = weatherData;
		weatherData.registerObserver(this);
	}

	public void update(float temperature, float humidity, float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		display();
	}

	public void display() {
		System.out.println("Current conditions: " + temperature + 
        			   "F degrees and " + humidity + "% humidity");
	}
}

Java의 Observable을 이용한 Observer Pattern

  • Java에 내장되어있는 Observable은 interface가 아닌 Class

 

  • setChanged() 메서드는 상태가 바뀌었다는 것을 알기 위한 용도 → java의 Observable에서는 setChanged()를 하지 않으면 notifyObservers()를 호출한다해도 옵저버들에게 알림이 가지 않음. → setChanged()가 일종의 필터(중간다리)역할
  • WeatherData에서는 더이상 observer를 등록해주거나 삭제, 알려주는 메서드를 작성할 필요가 없음

 

  • java.util.Observable의 단점
    • Observable은 class 이기 때문에 다중상속이 불가능하므로 다른 클래스를 상속하는 클래스는 Observable의 자식클래스가 될 수 없음
    • setChanged() 메서드는 protected로 선언되어 있는데 이는 즉, Observable를 상속받는 클래스가 아니면 setChanged를 호출할 수 없음.
      → Observable을 상속받는 객체를 다른 패키지에서 인스턴스 변수로 써먹을 수 없음
      → 이는 ‘상속보다는 구성하라(favor composition over inheritance)’ 디자인 설계 원칙에 어긋남

결론

 

  • Observer Pattern은 행위 패턴(Behavioral Pattern)의 하나로써 한 객체의 상태 변화에 따라 다른 객체의 상태도 연동되도록(알려주도록) 일대 다 객체 의존 관계를 구성하는 패턴
  • 장점
    • 느슨한 결합으로 인하여 시스템이 유연해지고 객체간의 의존성을 제거할 수 있음
    • 실시간으로 한 객체의 변경사항을 다른 객체에 전달할 수 있음
  • 단점
    • Thread safe하지 않아서 observer를 등록 / 제거 하는 동안 원하는 결과값을 얻기 힘들 수 있음
    • observer를 제 때 제거해주지 않으면 메모리 누수가 일어날 수 있음
    • 너무 많이 사용하게 되면 상태 관리가 힘들 수 있음

 


본문은 Head First Design Pattern (2004) 를 참고하여 공부하고 작성하였습니다.


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

06. Singleton Pattern  (0) 2022.08.21
05. Abstract Factory Pattern  (0) 2022.08.20
04. Factory Method Pattern  (0) 2022.08.18
03. Decorator Pattern  (0) 2022.04.30
01. Strategy Pattern  (0) 2022.03.12
Comments