[디자인패턴]옵저버 패턴

gov's avatar
Nov 14, 2024
[디자인패턴]옵저버 패턴
💡
Observer Pattern 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴
옵서버 observer 관찰자(참관인) 회의 등에서 정식 멤버로는 인정되지 않으나, 특별히 출석이 허용된 사람

특징

마트와(Subject) 손님(Observer)로 비유시, 마트에 상품이 들어오면 손님에게 알림이 가는 형식
  • 푸쉬 시스템 기반 주체(Subject)가 상태 변화를 감지하면 등록된 모든 관찰자(Observer)에게 자동으로 변화 내용을 푸쉬. 관찰자는 별도의 요청을 하지 않아도 주체로부터 변화를 즉시 전달 받음
  • 클래스의 의존성이 낮아 느슨한 결합을 유지. 인터페이스와 추상 클래스를 통해 상호작용
  • 한정된 시간, 특정 케이스에 다른 객체를 관찰할 때 사용
  • 구현방식
    • notifyObserver 한 개의 관찰 대상자(Subject)와 여러 관찰자(Observer A, B, C)로 일 대 다 관계 구성
    • update 관찰 대상의 상태가 바뀌면 변경사항을 옵저버에 통보
    • 통보받은 Observer는 값을 바꾸거나 삭제 등 대응. Observer는 언제든 Sub 그룹에 추가 및 삭제될 수 있다

예시 코드

sub

  • SubListener 인터페이스
    • 관찰자 역 인터페이스로, update메서드 정의
      Pub 클래스가 해당 인터페이스 타입 이용하여 관찰자 목록 관리
  • sub1, 2 클래스 SubListener 인터페이스를 구현한 구독자 역. update 메서드를 통해 주체(Subject)로부터 알림을 수신

pub

  • 구독자 관리 및 알림 메서드
    • Pub 클래스의 addremove 메서드는 구독자 목록(subList)을 관리
  • PubListener 인터페이스
    • notifyChange : 주체인 Pub의 상태 변화가 발생 시, 각 구독자(관찰자)에게 알림 전달
    • sub.update(msg);SubListener 인터페이스의 update 메서드를 호출로, 각 구독자가 update 메서드를 통해 메시지를 받음
package ch07; import ch07.pub.Pub; import ch07.pub.PubListener; import ch07.sub.Sub1; import ch07.sub.Sub2; import ch07.sub.SubListener; // 옵저버 패턴 -> 콜(구독)백(나중에) public class App { public static void main(String[] args) { // 1. 객체 생성 init -최초 등록 시, 모든 필요 객체 등록 PubListener pub = new Pub(); SubListener sub1 = new Sub1(); SubListener sub2 = new Sub2(); // 2. 구독하기 pub.add(sub1); pub.add(sub2); // 3. 상품 들어옴(가정) // 4. notifyChange 호출 -상품이 들어왔으니 호출 pub.notifyChange("상품 들어옴"); } }
package ch07.pub; import ch07.sub.SubListener; public interface PubListener { // 예) pub 마트, sub 손님 void add(SubListener sub); // 서버 컬렉션 등록 -Sub 구현체 가짐 void remove(SubListener sub); // 서버 컬렉션 제거 -Sub에서 어떤 객체인지 받기 void notifyChange(String msg); // 변화 알림 -상품 입고 시 실행 }
package ch07.pub; import ch07.sub.SubListener; import java.util.ArrayList; import java.util.List; public class Pub implements PubListener{ // 구독자 명단 List<SubListener> subList = new ArrayList<>(); @Override public void add(SubListener sub) { subList.add(sub); } @Override public void remove(SubListener sub) { subList.remove(sub); } // 책임: 물건이 들어오면, 구독자들에게 알림을 보냄 @Override public void notifyChange(String msg) { // 5초 잠자기 for (int i = 1; i < 6; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("."); } // 구독자에게 알림주기 for(SubListener sub : subList){ sub.update(msg); } } }
package ch07.sub; public class Sub1 implements SubListener { @Override public void update(String msg) { System.out.println("Sub1이 받은 알림: " + msg); } } package ch07.sub; public class Sub2 implements SubListener { @Override public void update(String msg) { System.out.println("Sub2가 받은 알림: " + msg); } }
package ch07.sub; public interface SubListener { void update(String msg); }

출력

notion image
Share article

goho