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

Stupefyee's avatar
Nov 14, 2024
[디자인 패턴] 옵저버 패턴
 
💡
객체 지향 프로그래밍에서 사용되는 디자인 패턴 중 하나로, 객체의 상태 변화가 있을 때 이를 감지하여 자동으로 다른 객체들에게 알리고 업데이트하는 패턴

1. 주요 구성 요소

  1. 주체 (Subject): 상태를 관리하며, 상태가 변화할 때 옵저버들에게 알림을 보냄.
  1. 옵저버 (Observer): 주체의 상태 변화를 감지하고 그에 따라 반응함.
  1. 구독 (Subscription): 옵저버가 주체에 등록되어 상태 변화를 구독.

2. 흐름

  • 주체(Subject)가 상태를 변경함.
  • 주체(Subject)는 자신에게 등록된 옵저버들(Observer)에게 변경 사항을 통지함.
  • 옵저버(Observer)는 주체(Subject)의 상태 변화를 감지하고, 그에 맞는 행동을 취함.

3. 예시

  1. 뉴스 사이트 예시
      • 뉴스 사이트의 주체인 뉴스 서버가 새로운 기사가 추가되면, 이를 구독하고 있는 옵저버들(예: 이메일 구독자, 모바일 앱 사용자)에게 자동으로 알림을 보냄.
      • 클라이언트가 일정 시간 간격으로 상태 확인을 위한 요청을 보냄.
      • 클라이언트가 새 기사를 구독하고 있으면, 기사가 업데이트 될 때마다 이메일이나 푸시 알림을 통해 변경 사항을 받음.
  1. 주식 거래 예시
      • 주식의 주체인 주식 시장에서 주식 가격이 변동하면, 주식을 구독하는 옵저버들(예: 투자자, 거래 시스템)은 가격 변화에 대한 알림을 받음.
      • 주식의 가격이 일정 비율 이상 변동하면 자동으로 알림을 보냄.

4. 장점

  • Loose Coupling: 주체와 옵저버는 서로 독립적이기 때문에 주체의 변경이 옵저버에 영향을 주지 않음.
  • 동적 구독: 옵저버는 필요에 따라 주체에 등록하거나 해제할 수 있음.

5. 단점

  • 과도한 알림: 옵저버가 많으면 불필요한 알림이 많아질 수 있음.
  • 상태 변화가 빈번한 경우: 많은 옵저버들에게 빈번하게 상태 변화 알림을 보내는 것이 성능에 영향을 줄 수 있음.

6. 활용 예시

  • 주식 거래 시스템
  • 날씨 정보 제공 시스템
  • 소셜 미디어 알림 시스템

7. 예제 코드

public interface PubListener { void add(SubListener sub); void remove(SubListener sub); void notifyChange(String msg); }
상태를 관리하는 PubListener.java
import ch07.sub.SubListener; import java.util.ArrayList; import java.util.List; public class Pub implements PubListener{ // 1. 구독자 명단 List<SubListener> subList = new ArrayList<>(); @Override public void add(SubListener sub) { subList.add(sub); } @Override public void remove(SubListener sub) { subList.remove(sub); } // 2. 책임: 물건이 들어오면, 구독자들에게 알림을 보냄 @Override public void notifyChange(String msg) { // 5초 잠자기 for (int i = 0; i < 6; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.print("."); } // 구독자들에게 알림주기 for (SubListener sub : subList) { sub.update(msg); } } }
PubListener 구현체 Pub.java
public interface SubListener { void update(String msg); }
상태를 관찰하는 SubListener.java
public class Sub1 implements SubListener{ @Override public void update(String msg) { System.out.println("sub1이 받은 알림: " + msg); } } public class Sub2 implements SubListener{ @Override public void update(String msg) { System.out.println("sub2가 받은 알림: " + msg); } }
SubListener 구현체 Sub1,2.java
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) { // 객체 생성 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("상품 입고됨"); } }
옵저버 패턴 실행을 위한 App.java

7.1. 출력문

💡
......sub1이 받은 알림: 상품 입고됨 sub2가 받은 알림: 상품 입고됨
현재 코드에서는 상태의 변화를 표현하고자 Thread.sleep();을 이용하여 지연 시간을 주어 구현한 상태.
아무 메시지가 없을때는 “.”으로 표현되다가 메시지를 입력 받으면 해당 메시지가 각 sub에 출력되는 모습
Share article

stupefyee