개발/디자인패턴

[Java][디자인 패턴] 18. 감시자 패턴 (Observer Pattern)

nova_dev 2022. 3. 22. 00:00
반응형

디자인패턴
[Java][디자인 패턴] 18. 감시자 패턴 (Observer Pattern)

감시자 패턴은 직접 상태 값을 관찰하는게 아니라 수동적으로 상태 값을 전달 받아 처리하는 패턴이다.

 

 감시자 패턴이란?

  • 감시자 패턴은 직접 상태 값을 관찰하는 것이 아니라 수동적으로 상태 값을 전달받아 처리하는 패턴이다.
  • 상태가 변경되었을 때 실제 동작하는 객체(Observer)에 통보하거나 갱신 작업을 통보한다.
  • 감시자 패턴은 상태를 감시하는 행동과 실제 동작을 처리하는 행동을 분리해서 구현한다.
  • 모던 언어에서 많이 응용되는 대표적인 패턴이다.
  • 단방향성의 감시자 패턴은 다른 말로 게시-구독(Publish-Subscribe) 패턴이라고 한다. 혹은 리스너 패턴(Listener Pattern)이라고도 한다.

 감시자 패턴 구조

  • 주체 (Subject)
    • 감시자 패턴에서 객체를 등록, 삭제, 통보를 담당하는 클래스
    • 실제 동작하는 모든 통보 객체 (Observer)는 주체에 등록되어야 한다.
  • 감시자 (Observer)
    • 상태가 변경될 경우 주체(Subject)는 감시자(Observer)에게 상태 변화를 통보한다. 이때 통보되는 감시자는 여러 개가 될 수 있다.
  • 실제 객체 (ConcreteObserver)
  • 실제 주체 (ConcreteSubject)

 감시자 패턴 예시 코드 구조

감시자 패턴 예제 코드 구조

 

예시 코드는 쉽게 배워 바로 써먹는 디자인 패턴 책의 PHP 예시 코드를 Java로 바꾸고 일부 코드를 변형했다.
UserA, UserB라는 Observer가 있고, 해당 Observer를 Members라는 Subject에 등록해둔다. (addObserver)
그런 뒤에 나중에 전체 멤버에게 통보해야 하는 것이 있으면 notifyObserver() 메서드를 통해 등록된 모든 Observer에게 통보할 수 있는 구조이다.

 

 감시자 패턴 코드

1. Observer 추상 클래스

public abstract class Observer {
    private String name;

    public abstract void update();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2. Observer 구체 클래스 (UserA, UserB)

public class UserA extends Observer {
    public UserA(String name) {
        this.setName(name);
    }

    @Override
    public void update() {
        System.out.println(this.getName() + "을 갱신합니다.");
    }
}
public class UserB extends Observer {
    public UserB(String name) {
        this.setName(name);
    }

    @Override
    public void update() {
        System.out.println(this.getName() + "을 갱신합니다.");
    }
}

3. Subject 인터페이스

public interface Subject {
    void addObserver(Observer observer);

    void deleteObserver(Observer observer);

    void notifyObserver();
}

4. Subject를 구현한 Members 클래스
Observer를 받아서 List로 등록해둔다. 통보할 것이 있다면 등록된 모든 Observer에게 통보할 수 있다.

public class Members implements Subject {
    private List<Observer> observerList;

    public Members() {
        this.observerList = new ArrayList<>();
    }

    @Override
    public void addObserver(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void deleteObserver(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObserver() {
        observerList.forEach(Observer::update);
    }
}

5. 테스트 코드

class MembersTest {

    @Test
    @DisplayName("감시자 패턴 테스트")
    void observerTest() {
        Subject subject = new Members();
        Observer observer1 = new UserA("jiae");
        Observer observer2 = new UserA("nova");
        subject.addObserver(observer1);
        subject.addObserver(observer2);
        
        subject.notifyObserver();
    }
}

결과

jiae을 갱신합니다.
nova을 갱신합니다.

 

 Github 코드

Github 예제 코드 링크

Github 예제 테스트 코드 링크

참고 자료

 

 

 

 

 

반응형