Menu
Coddy logo textTech

옵저버 패턴

Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 92번째.

옵저버 패턴(Observer pattern)은 객체 간의 일대다(one-to-many) 관계를 설정합니다. 하나의 객체(주체, subject)의 상태가 변경되면, 모든 의존 객체(옵저버, observers)들이 자동으로 알림을 받습니다. 이는 UI 업데이트, 이벤트 시스템 또는 애플리케이션의 여러 부분이 변경 사항에 반응해야 하는 모든 상황에 적합합니다.

이 패턴은 두 가지 핵심 역할을 포함합니다: 관찰자 목록을 유지하고 변경 사항을 알리는 Subject와, 자신을 등록하고 업데이트에 응답하는 Observers입니다:

abstract class Observer {
  void update(String message);
}

class NewsAgency {
  final List<Observer> _observers = [];
  String _latestNews = '';

  void subscribe(Observer observer) {
    _observers.add(observer);
  }

  void unsubscribe(Observer observer) {
    _observers.remove(observer);
  }

  void publishNews(String news) {
    _latestNews = news;
    for (var observer in _observers) {
      observer.update(_latestNews);
    }
  }
}

class NewsChannel implements Observer {
  final String name;
  NewsChannel(this.name);

  @override
  void update(String message) {
    print('$name received: $message');
  }
}

void main() {
  var agency = NewsAgency();
  var cnn = NewsChannel('CNN');
  var bbc = NewsChannel('BBC');

  agency.subscribe(cnn);
  agency.subscribe(bbc);

  agency.publishNews('Breaking news!');
  // CNN 수신: Breaking news!
  // BBC 수신: Breaking news!
}

publishNews가 호출되면, 에이전시는 모든 구독된 옵저버들을 순회하며 그들의 update 메서드를 호출합니다. 옵저버는 언제든지 구독하거나 구독을 해지할 수 있어 시스템을 유연하고 느슨하게 결합된(loosely coupled) 상태로 만듭니다. 즉, 주체(subject)는 옵저버의 구체적인 타입을 알 필요가 없습니다.

challenge icon

챌린지

쉬움

옵저버(Observer) 패턴을 사용하여 주가 알림 시스템을 구축해 봅시다! 주식 티커(stock ticker)가 가격이 변할 때마다 여러 투자자에게 알림을 보내고, 각 투자자가 시장 업데이트에 자신만의 방식으로 반응할 수 있는 시스템을 만들 것입니다.

코드는 다음 두 개의 파일로 구성합니다:

  • stock_system.dart: 여기에 옵저버 시스템을 만듭니다:
    • void onPriceChange(String stockName, double price) 메서드를 가진 추상 클래스 Investor
    • Investor를 구현하는 DayTrader 클래스. name 필드를 가지며, onPriceChange 메서드는 다음을 출력합니다: [name] sees [stockName] at $[price] - Making quick trade!
    • Investor를 구현하는 LongTermInvestor 클래스. name 필드를 가지며, onPriceChange 메서드는 다음을 출력합니다: [name] notes [stockName] at $[price] - Holding steady.
    • 다음 기능을 가진 StockTicker 클래스 (주체):
      • String stockName 필드
      • 구독한 투자자들을 저장하는 프라이빗 리스트
      • 투자자를 추가하는 subscribe(Investor investor) 메서드
      • 투자자를 제거하는 unsubscribe(Investor investor) 메서드
      • 모든 구독된 투자자에게 새로운 가격을 알리는 updatePrice(double newPrice) 메서드
  • main.dart: 주식 시스템을 임포트하고 옵저버 패턴이 작동하는 모습을 보여줍니다:
    • DART라는 이름의 주식에 대한 StockTicker를 생성합니다.
    • 이름이 AliceDayTrader와 이름이 BobLongTermInvestor를 생성합니다.
    • 두 투자자 모두 티커에 구독시킵니다.
    • 가격을 150.50으로 업데이트합니다 (두 투자자 모두에게 알림이 가야 합니다).
    • 빈 줄을 하나 출력합니다.
    • 티커에서 Alice의 구독을 해제합니다.
    • 가격을 155.75로 업데이트합니다 (이제 Bob에게만 알림이 가야 합니다).

이것은 옵저버 패턴이 어떻게 느슨하게 결합된(loosely coupled) 시스템을 만드는지 보여줍니다. StockTicker는 자신이 알림을 보내는 대상이 데이 트레이더인지 장기 투자자인지 알 필요가 없으며, 단지 구독된 모든 대상의 onPriceChange를 호출할 뿐입니다!

예상 출력:

Alice sees DART at $150.5 - Making quick trade!
Bob notes DART at $150.5 - Holding steady.

Bob notes DART at $155.75 - Holding steady.

치트 시트

옵저버 패턴(Observer pattern)은 주체의 상태가 변경될 때 모든 옵저버에게 알림을 보내는 일대다 관계를 설정합니다.

이 패턴에는 두 가지 핵심 역할이 있습니다:

  • Subject (주체): 옵저버 목록을 유지하고 변경 사항을 알립니다
  • Observer (옵저버): 주체에 등록하고 업데이트에 응답합니다

기본 구현:

abstract class Observer {
  void update(String message);
}

class Subject {
  final List<Observer> _observers = [];

  void subscribe(Observer observer) {
    _observers.add(observer);
  }

  void unsubscribe(Observer observer) {
    _observers.remove(observer);
  }

  void notifyObservers(String data) {
    for (var observer in _observers) {
      observer.update(data);
    }
  }
}

class ConcreteObserver implements Observer {
  final String name;
  ConcreteObserver(this.name);

  @override
  void update(String message) {
    print('$name received: $message');
  }
}

주요 장점:

  • 주체와 옵저버 간의 느슨한 결합
  • 옵저버가 동적으로 구독/해지할 수 있음
  • 주체가 특정 옵저버 유형을 알 필요가 없음

직접 해보기

import 'stock_system.dart';

void main() {
  // TODO: 'DART'라는 이름의 주식을 위한 StockTicker 생성
  
  // TODO: 'Alice'라는 이름의 DayTrader 생성
  
  // TODO: 'Bob'이라는 이름의 LongTermInvestor 생성
  
  // TODO: 두 투자자 모두 ticker에 구독
  
  // TODO: 가격을 150.50으로 업데이트 (두 투자자 모두에게 알림이 가야 함)
  
  // TODO: 빈 줄 출력
  
  // TODO: ticker에서 Alice 구독 해제
  
  // TODO: 가격을 155.75로 업데이트 (이제 Bob에게만 알림이 가야 함)
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨