[헤드 퍼스트 디자인 패턴] 옵저버 패턴

햐얀하늘·2024년 5월 15일
0

디자인 패턴 - 옵저버 패턴에 대해 알아보자!

옵저버 패턴의 정의

  • 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의

즉 유투버와 유투브 구독자가 알림설정한 거라고 보면된다. 유튜버가 새로운 영상을 올리면 구독자는 알림설정을 통해 새로운 영상이 나왔다는 것을 알게 된다. 이처럼 옵저버 패턴은 One To Many 관계를 맺고 있다.

옵저버 패턴의 예시

  • 날씨 정보를 가져오는 기상청이 있고 기상청은 여러 지역구에 기상 정보를 내려주는 것을 옵저버 패턴을 이용해 구현해보자
  1. Observer 인터페이스와 Subject 인터페이스를 구현하자 그리고 이런 정보를 보여주는 display 인터페이스를 정의하자
  • Subject 인터페이스는 옵저버를 등록하고 삭제하며 옵저버에 알림보내주는 메소드가 존재한다.(ex 기상청)
  • Observer 인터페이스는 정보를 update하는 method가 존재하고 옵저버 클래스가 상속받는다.(ex 지역구)
public interface Subject {
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObservers();
}
public interface Observer {
	public void update(float temp, float humidity, float pressure);
}
public interface DisplayElement {
	public void display();
}
  1. Subject를 상속받아 옵저버들을 관리하고 정보를 내려주는 클래스를 구현해보자
package headfirst.designpatterns.observer.weather;

import java.util.*;

public class WeatherData implements Subject {
	//옵저버들 목록
	private List<Observer> observers;
	private float temperature;
	private float humidity;
	private float pressure;
	
  	// 객체 생성시 observers 목록 초기화
	public WeatherData() {
		observers = new ArrayList<Observer>();
	}
	
    // 옵저버 등록
	public void registerObserver(Observer o) {
		observers.add(o);
	}
	
    // 옵저버 삭제
	public void removeObserver(Observer o) {
		observers.remove(o);
	}
	
    // 모든 옵저버들에게 공지내려줌
	public void notifyObservers() {
		for (Observer observer : observers) {
			observer.update(temperature, humidity, pressure);
		}
	}
	
    // 변화가 인지되면 옵저버들에게 공지
	public void measurementsChanged() {
		notifyObservers();
	}
	
    // temperature, humidity, pressure를 저장하고 옵저버들에게 공지
	public void setMeasurements(float temperature, float humidity, float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementsChanged();
	}
	
    //온도 get
	public float getTemperature() {
		return temperature;
	}
	
    // 습도 get
	public float getHumidity() {
		return humidity;
	}
	
    // 기압 get
	public float getPressure() {
		return pressure;
	}

}
  1. 옵저버를 만들어 보자! - 현재 온도를 보여주는 옵저버
package headfirst.designpatterns.observer.weather;
	
public class CurrentConditionsDisplay implements Observer, DisplayElement {
	private float temperature;
	private float humidity;
	private WeatherData weatherData;
	
    // 생성자 -> weather 의존성 주입하고 weatherData에 옵저버 등록
	public CurrentConditionsDisplay(WeatherData weatherData) {
		this.weatherData = weatherData;
		weatherData.registerObserver(this);
	}
	
    // update 시에는 온도와 습도를 저장하고 display 해줌
	public void update(float temperature, float humidity, float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		display();
	}
	
    // 온도 습도 기압을 보여주는 display
	public void display() {
		System.out.println("Current conditions: " + temperature 
			+ "F degrees and " + humidity + "% humidity");
	}
}
  1. 그렇다면 기상청을 생성해서 정보를 보내주자
public class WeatherStation {

	public static void main(String[] args) {
		WeatherData weatherData = new WeatherData();
	
		CurrentConditionsDisplay currentDisplay = 
			new CurrentConditionsDisplay(weatherData);


		weatherData.setMeasurements(80, 65, 30.4f); // weatherData가 변경되어 옵저버인 currentDisplay에 정보를 보내주고 update 동작 실행됨
		weatherData.setMeasurements(82, 70, 29.2f); // weatherData가 변경되어 옵저버인 currentDisplay에 정보를 보내주고 update 동작 실행됨
		weatherData.setMeasurements(78, 90, 29.2f); // weatherData가 변경되어 옵저버인 currentDisplay에 정보를 보내주고 update 동작 실행됨

	}
}

이렇게 옵저버 패턴을 만들어 봤다.

ps) 회사에서 이 패턴을 어떻게 써야하지.. 어떤 거에 접목시키면 좋을지 감이 안잡힌다. 아는것과 실제로 적용시키는건 어려운것 같다...
다른 객체의 결합도를 줄이고 객체의 통신을 유연하게 만드는 것 고민해봐야겠다.

profile
나는 커서 개발자가 될거야!

0개의 댓글