옵저버 패턴
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)는 옵저버의 구체적인 타입을 알 필요가 없습니다.
챌린지
쉬움옵저버(Observer) 패턴을 사용하여 주가 알림 시스템을 구축해 봅시다! 주식 티커(stock ticker)가 가격이 변할 때마다 여러 투자자에게 알림을 보내고, 각 투자자가 시장 업데이트에 자신만의 방식으로 반응할 수 있는 시스템을 만들 것입니다.
코드는 다음 두 개의 파일로 구성합니다:
stock_system.dart: 여기에 옵저버 시스템을 만듭니다:void onPriceChange(String stockName, double price)메서드를 가진 추상 클래스InvestorInvestor를 구현하는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를 생성합니다.- 이름이
Alice인DayTrader와 이름이Bob인LongTermInvestor를 생성합니다. - 두 투자자 모두 티커에 구독시킵니다.
- 가격을
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에게만 알림이 가야 함)
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.