[디자인 패턴] 옵저버 패턴

Narcoker·2023년 8월 1일
0

디자인 패턴

목록 보기
5/8

옵저버 패턴

옵저버 패턴(Observer Pattern)은 소프트웨어 디자인 패턴 중 하나로서,
객체 간의 일대다 의존성을 정의한다.

이 패턴은 한 객체의 상태가 변경될 때마다
그 객체에 종속된 모든 객체에 그 변경사항을 자동으로 알린다.

옵저버 패턴은 주로 분산 이벤트 핸들링 시스템,
모델-뷰-컨트롤러 (MVC) 아키텍처, 비동기 프로그래밍 등에서 사용된다.

옵저버 패턴이 생기기 전에는 Polling 방식을 이용해서
일정 주기로 이벤트를 감지하고 상태를 업데이트 했다.

만약 확인 주기가 1시간이라고 가정해보자
1시간 안에 이벤트가 생기고 제거되면 인식할 수 없게 된다.
이러한 점을 해결하기 위해서 나온 것이 옵저버 패턴이다.

주요 구성 요소

Subject

이는 관찰의 대상이 되는 객체로, Observer들이 업데이트를 받는 대상이다.
Subject는 Observer를 등록하고, 삭제하고, 알림을 보내는 메소드를 제공한다.

Observer

Subject의 상태 변화를 관찰하는 객체들이다.
모든 Observer는 업데이트 메소드를 갖는다.

ConcreteSubject

Subject의 구체적인 클래스이다.
상태가 변할 때마다 Observer에게 알린다.

ConcreteObserver

Observer의 구체적인 클래스로, 상태 변화를 받아 처리한다.

장점

객체 간의 느슨한 결합(loose coupling)

Observer는 Subject의 구체적인 클래스를 알 필요가 없으며,
Subject는 Observer의 구체적인 클래스에 대해 알지 못한다.

새로운 Observer를 추가하는 것이 쉽다

이는 Observer 인터페이스를 구현하는 새로운 클래스를 추가함으로써 이루어진다.

단점

많은 시간 소요

Observer가 많아지면, 모든 Observer에게 알림을 보내는 데 많은 시간이 소요될 수 있다.

메모리 누수 발생

Observer와 Subject가 서로 참조하고 있다면, 메모리 누수가 발생할 수 있다.

예제

Observer와 Subject 인터페이스를 정의

// Observer 인터페이스
public interface Observer {
   void update();
}

// Subject 인터페이스
public interface Subject {
   void registerObserver(Observer observer);
   void removeObserver(Observer observer);
   void notifyObservers();
   WeatherData getState();
}

// WeatherData 클래스
public class WeatherData {
   private float temperature;
   private float humidity;
   private float pressure;

   // getters and setters ...
}

Observer와 Subject를 구현하는 ConcreteObserver와 ConcreteSubject를 정의

// ConcreteObserver: CurrentConditionsDisplay
public class CurrentConditionsDisplay implements Observer {
    private Subject weatherStation;

    public CurrentConditionsDisplay(Subject weatherStation) {
        this.weatherStation = weatherStation;
        weatherStation.registerObserver(this);
    }

    @Override
    public void update() {
        WeatherData data = weatherStation.getState();
        System.out.println("Current conditions: " + data.getTemperature() 
            + "F degrees and " + data.getHumidity() + "% humidity");
    }
}

// ConcreteSubject: WeatherStation
public class WeatherStation implements Subject {
    private List<Observer> observers;
    private WeatherData weatherData;

    public WeatherStation() {
        this.observers = new ArrayList<>();
        this.weatherData = new WeatherData();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.weatherData.setTemperature(temperature);
        this.weatherData.setHumidity(humidity);
        this.weatherData.setPressure(pressure);
        notifyObservers();
    }

    @Override
    public WeatherData getState() {
        return weatherData;
    }
}

옵저버 패턴 테스트

public class WeatherStationSimulator {
    public static void main(String[] args) {
    	// Subject
        WeatherStation weatherStation = new WeatherStation();
		
        // Observer
        CurrentConditionsDisplay currentDisplay = 
        	new CurrentConditionsDisplay(weatherStation);

        weatherStation.setMeasurements(80, 65, 30.4f);
        weatherStation.setMeasurements(82, 70, 29.2f);
    }
}
profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글