Observer Pattern

보람찬하루·2024년 9월 20일
1

design-pattern

목록 보기
1/2
post-thumbnail

배경

인턴활동을 하며 실 업무에 들어가기 위해 기존 코드를 학습하는 과정 중에 있다. 기존 코드를 학습하기 위해 기존 코드에 사용되어있는 디자인 패턴을 학습하려고 한다. 오늘은 옵저버 패턴이 사용된 부분을 이해하기 위해 Oberver Pattern을 학습해보았다.


주제

Oberver Pattern


내용

의미

옵저버 패턴(Observer Pattern) : 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고, 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의

옵저버 패턴(Observer Pattern)은 객체 간의 일대다(One-to-Many) 의존 관계를 정의하는 디자인 패턴입니다. 한 객체의 상태가 변경되면, 그 상태에 의존하는 다른 객체들(옵저버)에게 자동으로 통지되고, 그 결과 이들 객체의 상태도 자동으로 갱신됩니다. 주로 이벤트 기반 시스템에서 많이 사용됩니다.


이미지1
이미지2

간단한 예로, 아파트 중개를 생각해볼 수 있습니다. 사용자가 특정 아파트에 관심이 있을 때, 매번 방이 있는지 없는지를 확인하기 위해 지속적으로 중개업체에 연락을 해야 한다면 비효율적일 것입니다. 대신, 옵저버 패턴을 적용하면, 사용자는 한 번만 관심 아파트를 등록해두면 중개업체(주제 객체)가 방이 생길 때 알아서 연락을 해줍니다.

옵저버 패턴 전과 후 비교

옵저버 패턴 적용 전 )

  • 사용자가 반복적으로 "방 있나요?"라고 질문해야 합니다.

옵저버 패턴 적용 후 )

  • 사용자는 한 번만 관심을 등록하면, 중개업체가 방이 생길 때 알아서 연락을 줍니다.

옵저버 패턴의 세 가지 핵심 단계

  1. 등록: 사용자가 중개업체에 특정 아파트에 관심이 있다고 등록합니다.
  2. 해제: 더 이상 아파트에 관심이 없으면 등록을 해제할 수 있습니다.
  3. 알림: 방이 생기면 중개업체가 사용자에게 자동으로 알립니다.

옵저버 패턴의 구조

옵저버 패턴의 구조는 크게 두 가지 주요 인터페이스로 나뉩니다: 주제(Subject)옵저버(Observer).

1. 주제(Subject) 인터페이스

Subject 인터페이스는 옵저버를 등록, 제거하고 상태 변경 시 옵저버에게 알리는 역할을 담당합니다. 주제는 상태가 변경될 때마다 옵저버에게 상태 변경 사실을 통지합니다.


interface Subject {
    void registerObserver(Observer o); // 옵저버 등록
    void removeObserver(Observer o);   // 옵저버 삭제
    void notifyObservers();            // 옵저버에게 업데이트 알림
}

class SubjectImpl implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String state;

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

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

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

    public String getState() {
        return state;
    }

    public void setState(String newState) {
        this.state = newState;
        notifyObservers(); // 상태 변경 시 옵저버들에게 알림
    }
}
  • registerObserver(): 옵저버를 리스트에 등록합니다.
  • removeObserver(): 리스트에서 옵저버를 제거합니다.
  • notifyObservers(): 상태가 변경되면 등록된 모든 옵저버에게 알림을 보냅니다.

2. 옵저버(Observer) 인터페이스

Observer 인터페이스는 주제의 상태가 변경되었을 때 이를 감지하고 자신의 상태를 업데이트하는 메소드를 포함합니다. 옵저버는 주제의 상태 변화에 따라 필요한 행동을 정의할 수 있습니다.

interface Observer {
    void update(String newState); // 주제의 상태가 변경되었을 때 호출됨
}

class ObserverImpl implements Observer {
    private String observerState;

    @Override
    public void update(String newState) {
        this.observerState = newState;
        display();
    }

    public void display() {
        System.out.println("옵저버 상태가 업데이트 되었습니다: " + observerState);
    }
}
  • update(): 주제로부터 새로운 상태를 전달받아 자신의 상태를 갱신합니다.

예제 시나리오: 날씨 모니터링 시스템

옵저버 패턴은 날씨 모니터링 시스템과 같은 실시간 정보 전달 시스템에서 많이 사용됩니다. 날씨 센서(주제)가 온도, 습도 등의 정보를 업데이트하면, 이를 구독한 디스플레이 장치(옵저버)가 상태를 자동으로 갱신합니다.


class WeatherData implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;

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

    public void measurementsChanged() {
        notifyObservers();
    }

    public void setMeasurements(float temperature, float humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
        measurementsChanged();
    }

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

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

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

class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

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

    public void display() {
        System.out.println("현재 상태: 온도 " + temperature + "도, 습도 " + humidity + "%");
    }
}

이 예제에서는 WeatherData 객체가 주제 역할을 하고, CurrentConditionsDisplay 객체가 옵저버 역할을 합니다. 날씨 데이터가 갱신되면, 자동으로 옵저버들에게 알림을 보내고 상태가 업데이트됩니다.


옵저버 패턴의 장단점

장점:

  1. 느슨한 결합(Loose Coupling): 주제와 옵저버가 느슨하게 결합되어 있습니다. 즉, 주제는 옵저버가 누구인지 또는 옵저버가 무엇을 하는지 알 필요가 없습니다. 이로 인해 시스템 확장이 용이해집니다.
  2. 유연한 설계: 새로운 옵저버를 쉽게 추가하거나 제거할 수 있으며, 각 옵저버는 독립적으로 동작합니다.
  3. 실시간 정보 갱신: 주제의 상태가 바뀔 때마다 옵저버들이 자동으로 갱신되어, 실시간으로 정보를 반영할 수 있습니다.

단점:

  1. 성능 저하: 주제에 등록된 옵저버가 많을 경우, 주제가 상태를 변경할 때 모든 옵저버에게 알림을 보내는 데 시간이 오래 걸릴 수 있습니다.
  2. 복잡성 증가: 작은 시스템에서는 패턴 적용이 불필요할 수 있으며, 잘못 사용하면 코드가 더 복잡해질 수 있습니다.

결론

옵저버 패턴은 이벤트 기반 시스템이나 실시간 데이터 전달이 필요한 시스템에서 매우 유용한 디자인 패턴입니다. 여러 객체가 동일한 주제의 상태에 의존해야 하거나, 상태 변경을 알림받아야 할 때 유용합니다. 느슨한 결합과 유연성을 제공하는 반면, 사용 범위에 따라 성능 저하나 복잡성을 초래할 수 있으므로 적절한 상황에 맞게 적용하는 것이 중요합니다.

profile
를 만들어 가자

1개의 댓글

comment-user-thumbnail
2024년 10월 15일

멋있어여

답글 달기