본문 바로가기

Computer Science/Design Pattern

[게임 프로그래밍 패턴] 3. 관찰자 패턴

관찰자 패턴 (Observer Pattern)

70 : 관찰자 패턴을 적용하면 어떤 코드에서 흥미로운 일이 생겼을 때 누가 받든 상관없이 알림을 보낼 수 있다.

81 : 대상이나 관찰자를 제거하면 어떻게 될 것인가라는 중요한 문제가 있다. 관찰자를 부주의하게 삭제하다 보면 대사에 있는 포인터가 이미 삭제된 객체를 가리킬 수 있다.
대상이 제거될 경우에는 '사망' 메시지를 관찰자에게 전달함으로써 관찰자가 기다리는 것을 막을 수 있다.
관찰자가 제거될 때 대상에 있는 관찰자도 제거하려면, 관찰자도 대상을 관리하고 있어야하기 때문에 상호참조가 생겨 복잡성이 늘어날 수 있다.
사라진 리스너 문제 해결 필요

83 : 관찰자 패턴을 사용하는 이유는 두 코드 간의 결합을 최소화하기 위해서다. 덕분에 대상은 다른 관찰자와 정적으로 묶이지 않고도 간접적인 상호작용을 할 수 있다.
하지만 그렇기 때문에 프로그램에서 코드가 어떻게 상호작용하는지를 정적으로는 알 수 없고 명령 실행 과정을 동적으로 추론해야 한다.
관찰자 패턴은 서로 연관 없는 코드 덩어리들이 하나의 큰 덩어리가 되지 않으면서 서로 상호작용하기에 좋은 방법이지, 하나의 기능을 구현하기 위한 코드 덩어리 안에서는 그다지 유용하지 않다.

public class Observer {
    // 다른 param을 전달받아서 다양한 처리를 할 수 있음
    public void onNotified(String message) {
        System.out.println(message);
    }
}
public class Subject {
    private List<Observer> observers = new LinkedList<>();

    public void doSomething() {
        System.out.println("--- 무언가를 하는 코드 --- ");

        notify("대상이 뭔가를 합니다");
    }
    public void runAway() {
        System.out.println("--- 도망치는 코드 --- ");

        notify("대상이 도망칩니다.");
    }

    public void add(Observer observer) {
        observers.add(observer);
    }
    public void remove(Observer observer) {
        observers.remove(observer);
    }
    private void notify(String message) {
        observers.forEach(observer -> observer.onNotified(message));
    }
}
public class Main {
    public static void main(String[] args) {
        Observer observer = new Observer();

        Subject subject = new Subject();
        subject.add(observer);

        subject.doSomething();
        subject.runAway();
    }
}

// 실행결과
--- 무언가를 하는 코드 --- 
대상이 뭔가를 합니다
--- 도망치는 코드 --- 
대상이 도망칩니다.