Computer Science/Design Pattern

[Design Pattern] 옵저버 패턴 (Observer Pattern)

dbssk 2023. 10. 8. 07:28

옵저버 패턴(Observer Pattern)

  • 어떤 대상의 상태가 변경되었을 때 이 상태 변경에 연관이 있는 관찰자들에게 알려주는 패턴

  • 장점
    • 느슨한 결합(Loose Coupling) : 주체(Subject)와 옵저버는 서로에 대한 최소한의 정보만 알고 있어야 한다. 이로써 시스템의 유연성이 향상되며 요구사항 변경에 대응하기 쉬워진다.

  • 단점
    • 메모리 누수(Lapsed Listener Problem) : 주체 객체가 명시적으로 옵저버를 등록하고 해제하지 않으면 메모리 누수가 발생할 수 있다. 즉, 더 이상 필요하지 않은 옵저버가 주체에 대한 참조를 유지하는 문제가 있을 수 있다.

  • 사용 사례
    • 1:1, 1:N 모두 가능하고 대부분 여러 객체가 한 객체의 상태 변화를 관찰하고 이에 반응해야 할 때 사용한다.
    • GUI 툴킷 : 많은 GUI 툴킷에서는 버튼과 클릭 리스너(OnClickListener)를 옵저버 패턴을 사용하여 모델링
    • 소셜 미디어 : 팔로우 기능과 같이 다른 사용자의 상태를 관찰하는 데 옵저버 패턴을 사용
    • RSS 피드 및 이메일 구독 : 새로운 업데이트 또는 메시지를 수신하는 사용자가 옵저버로 작동

 

옵저버 패턴 예시

주제(Subject) 인터페이스 정의

import java.util.List;

public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

옵저버(Observer) 인터페이스 정의

public interface Observer {
    void update(String message);
}

구체적인 주제 클래스 구현

import java.util.ArrayList;
import java.util.List;

public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String message;

    @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(message);
        }
    }

    public void setMessage(String message) {
        this.message = message;
        notifyObservers();
    }
}

구체적인 옵저버 클래스 구현

public class ConcreteObserver implements Observer {
    private String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + " received message: " + message);
    }
}

메인 클래스에서 사용

public class Main {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();

        ConcreteObserver observer1 = new ConcreteObserver("Observer 1");
        ConcreteObserver observer2 = new ConcreteObserver("Observer 2");

        subject.registerObserver(observer1);
        subject.registerObserver(observer2);

        subject.setMessage("Hello, Observers!");
    }
}

// 결과
Observer 1 received message: Hello, Observers!
Observer 2 received message: Hello, Observers!

 

 

[참고] https://www.geeksforgeeks.org/observer-pattern-set-1-introduction/