옵저버패턴...읭읭

yeolyeol·2024년 10월 23일
0

til

목록 보기
20/27
post-thumbnail

읭읭...


옵저버 패턴

옵저버 패턴
옵저버란 영어로 직역하면 관찰자라는 뜻이 있는데, 이러한 뜻처럼 어느 대상을 관찰하고 있다고 생각하면 된다. 그럼 관찰자가 보고 있는 대상에게 특이사항이 발견되면? 그럼 관찰자는 다른 누군가에게 그 상황을 알릴 것이다.

디자인 패턴 중 옵저버 패턴 역시 비슷한 역할을 한다.
관찰하고 있는 대상자의 상태가 변화가 있을 때마다 대상자는 직접 목록의 각 관찰자들에게 알리고, 관찰자들은 알림을 받아 조치를 위하는 행동 패턴이다.
또한 옵저버 패턴은 다른 패턴들과 다르게 One-To-Many 즉, 일대다 의존성을 갖는다. 왜냐하면 분산 이벤트 핸들링을 주로 구현하는 데에 사용되기 때문이며, Pub/Sub 모델로도 알려져 있다.

프로그램에서 옵저버 패턴은 관찰보단 갱신을 위한 정보를 전달받기를 기다린다고 보는 것이 정확하다.
그래서 능동적인 느낌보단 수동적인 느낌으로 생각하면 이해하기 편하다.

패턴 구조

크게 관찰 대상자와 관찰자로 나눠 볼 수 있다.

각 인터페이스와 구현체들에 대한 설명이다.

Subject : 관찰 대상

  • Subject<<Interface>>
    관찰 대상자를 정의하는 인터페이스다.
  • ConcreteSubject (implements Subject)
    관찰 당하는 대상자다. 앞서 말했던 것처럼 관찰자에게 변화를 알리는 역할이기 때문에, 발행자 또는 게시자 라고도 불린다.
    • Observers(): Observer들을 리스트(List, Map 등)로 모아서 관리하고 있다.
    • registerObserver() & removeObserver(): Subject의 역할은 관찰자인 Observer들을 내부 리스트에 등록/삭제 하는 메서드를 갖고 있다. (register, remove)
    • notifyObservers(): Subject가 상태를 변경하거나 어떤 동작을 실행할 때, Observer들에게 이벤트 알림을 발행한다.

Observer : 관찰자

  • Observer<<Interface>>
    관찰자를 정의하는 인터페이스다.
  • Observer
    관찰자, 구독자, 알림 수신자의 역할을 하는 구현체이다.
    • Observer들은 Subject가 발행한 알림에 대해 현재 상태를 취득한다.
    • update(): Subject의 상태 업데이트에 대해 전후 정보를 처리한다.

옵저버 패턴의 핵심은 옵저버들을 리스트로 관리하고 리스트에 있는 옵저버 객체들에게 모두 메서드 위임을 통하여 전파 행위를 한다는 점이다.

패턴 흐름

  1. 옵저버 패턴은 1개의 관찰 대상자(Subject)와 여러개의 관찰자(Observer)로 구성되어 있다. (1:N)
  2. 옵저버 패턴에서 관찰 대상 Subject의 상태가 바뀌면 변경사항을 notifyObserver()를 통해 옵저버한테 통보한다.
  3. 대상자로부터 통보를 받은 Observer는 update()를 통해 값을 수정하거나 삭제하는 등 적절한 대응을 할 수 있다.
  4. Observer들은 언제든지 Subject 그룹에 추가 또는 삭제될 수 있다. 즉, 구독을 했다가 취소했다가를 할 수 있게 된다. 즉, Subject를 관찰하는 상태라면 Subject의 이벤트에 대한 정보를 받을 수 있고, 그룹에 삭제된 상태라면 더이상 Subject의 정보를 받을 수 없게 된다.

코드로 보기

클래스 구조

  • Subject 인터페이스
interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObserver();
}
  • Subject 구현체 (관찰 대상자)
class ConcreteSubject implements Subject {
    // 관찰자들을 등록하여 담는 리스트
    List<IObserver> observers = new ArrayList<>();

    // 관찰자를 리스트에 등록
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
        System.out.println(o + " 구독 완료");
    }

    // 관찰자를 리스트에 제거
    @Override
    public void removeObserver(Observer o) {
        observers.remove(o);
        System.out.println(o + " 구독 취소");
    }

    // 관찰자에게 이벤트 송신
    @Override
    public void notifyObserver() {
        for(Observer o : observers) { // 관찰자 리스트를 순회하며
            o.update(); // 위임
        }
    }
}
  • Observer 인터페이스
interface Observer {
    void update();
}
  • Observer 구현체 (관찰자)
class ObserverA implements Observer {
    public void update() {
        System.out.println("ObserverA 한테 이벤트 알림이 왔습니다.");
    }

    public String toString() { return "ObserverA"; }
}

class ObserverB implements Observer {
    public void update() {
        System.out.println("ObserverB 한테 이벤트 알림이 왔습니다.");
    }

    public String toString() { return "ObserverB"; }
}

클래스 흐름

public class Client {
    public static void main(String[] args) {

        // 발행자 등록
        Subject publisher = new ConcreteSubject();

        // 발행자를 구독할 관찰자들 리스트로 등록
        Observer observer1 = new ObserverA();
        Observer observer2 = new ObserverB();
        publisher.registerObserver(observer1);
        publisher.registerObserver(observer2);

        // 관찰자에게 이벤트 전파
        publisher.notifyObserver();

        // ObserverB가 구독 취소
        publisher.removeObserver(observer2);

        // ObserverA 한테만 이벤트 전파
        publisher.notifyObserver();
    }
}
# 결과 화면
ObserverA 구독 완료
ObserverB 구독 완료
ObserverA 한테 이벤트 알림이 왔습니다.
ObserverB 한테 이벤트 알림이 왔습니다.
ObserverB 구독 취소
ObserverA 한테 이벤트 알림이 왔습니다.

특징

장/단점

  • 장점
  1. Subject의 상태 변경을 주기적으로 조회하지 않고 정해진 이벤트가 발생될 때마다 자동으로 감지가 가능하다.
  2. 관찰 대상자(발행자)의 코드를 변경하지 않고도 새 관찰자(구독자) 클래스를 도입할 수 있다. 이로 인해 SOLID 원칙 중 OCP를 준수한다.
  3. 런타임 시점에서 발행자와 구독 관계를 맺을 수 있다.
  4. 발행자와 구독자 간의 관계를 느슨하게 유지할 수 있다.
  • 단점
  1. 구독자는 알림 순서를 제어할 수 없어서 무작위로 알림을 받는다.
  2. 옵저버 패턴을 자주 구성하면 구조와 동작을 알아보기 힘들어져 코드 복잡도가 증가한다.
  3. 다수의 옵저버 객체를 등록 이후 해지하지 않으면 메모리 누수가 발생한다.

참고

https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%98%B5%EC%A0%80%EB%B2%84Observer-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90
https://yongj.in/design%20pattern/observer-pattern/

profile
한 걸음씩 꾸준히

0개의 댓글

관련 채용 정보