옵저버 패턴
Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 68번째.
옵저버 패턴(Observer Pattern)은 객체 간의 일대다 관계를 설정하는 행동 디자인 패턴입니다. 하나의 객체(주체(subject))의 상태가 변경되면, 그에 의존하는 모든 객체들(옵저버(observers))이 자동으로 알림을 받고 업데이트됩니다. 뉴스레터 구독과 같다고 생각하면 됩니다. 새로운 콘텐츠가 게시될 때마다 구독자들이 업데이트를 받는 방식입니다.
이 패턴은 두 가지 주요 구성 요소로 구성됩니다. 옵저버 목록을 유지하고 변경 사항을 알리는 주체(subject)와, 알림에 응답하기 위해 update 메서드를 정의하는 옵저버(observers)입니다:
import java.util.ArrayList;
import java.util.List;
interface Observer {
void update(String message);
}
class NewsPublisher {
private List<Observer> subscribers = new ArrayList<>();
public void subscribe(Observer observer) {
subscribers.add(observer);
}
public void unsubscribe(Observer observer) {
subscribers.remove(observer);
}
public void publish(String news) {
for (Observer subscriber : subscribers) {
subscriber.update(news);
}
}
}
class EmailSubscriber implements Observer {
private String email;
public EmailSubscriber(String email) {
this.email = email;
}
public void update(String message) {
System.out.println("Email to " + email + ": " + message);
}
}게시자가 뉴스를 발행하면 모든 구독자에게 자동으로 알림이 전송됩니다:
NewsPublisher publisher = new NewsPublisher();
publisher.subscribe(new EmailSubscriber("alice@mail.com"));
publisher.subscribe(new EmailSubscriber("bob@mail.com"));
publisher.publish("Breaking news!");
// 출력:
// alice@mail.com으로 이메일: Breaking news!
// bob@mail.com으로 이메일: Breaking news!옵저버 패턴(Observer Pattern)은 느슨한 결합(loose coupling)을 촉진합니다. 주체(subject)는 관찰자(observer)의 구체적인 클래스를 알 필요가 없으며, 단지 그들이 Observer 인터페이스를 구현한다는 사실만 알면 됩니다. 이를 통해 주체를 수정하지 않고도 새로운 관찰자 유형을 쉽게 추가할 수 있습니다.
챌린지
쉬움옵저버 패턴(Observer Pattern)을 사용하여 주가 알림 시스템을 구축해 봅시다! 주식 티커(stock ticker)가 주가 변동 시마다 여러 투자자에게 알림을 보내고, 각 투자자가 자신의 방식대로 가격 업데이트에 반응하는 시스템을 만들 것입니다.
코드는 다음 네 개의 파일로 구성됩니다:
Observer.java: 모든 투자자가 구현할Observer인터페이스를 정의합니다. 옵저버가 가격 변동 알림을 받는 데 사용하는 단일 메서드update(String stockName, double price)를 선언해야 합니다.StockTicker.java: 옵저버 목록을 유지하고 가격 변동을 알리는 주체(subject) 클래스를 생성합니다.StockTicker는 다음을 포함해야 합니다:주식 이름을 위한 private String 필드 (생성자를 통해 설정).
현재 가격을 위한 private double 필드 (초기값은 0).
구독한 옵저버들을 저장할 private 리스트.
리스트에 옵저버를 추가하는
subscribe(Observer observer)메서드.리스트에서 옵저버를 제거하는
unsubscribe(Observer observer)메서드.가격을 업데이트한 후, 모든 옵저버의
update메서드를 주식 이름과 새 가격으로 호출하여 알림을 보내는setPrice(double price)메서드.Investors.java:Observer인터페이스를 구현하는 두 가지 유형의 투자자를 생성합니다:DayTrader- 생성자를 통해 설정되는 private name 필드를 가집니다. 업데이트 시,[name] received alert: [stockName] is now $[price] - Making quick trade!를 출력합니다.LongTermInvestor- 생성자를 통해 설정되는 private name 필드를 가집니다. 업데이트 시,[name] received alert: [stockName] is now $[price] - Holding steady.를 출력합니다.가격은 소수점 둘째 자리까지 포맷팅하여 출력하세요.
Main.java: 옵저버 시스템을 하나로 합칩니다! 주식 이름(String), 첫 번째 가격 업데이트(double), 두 번째 가격 업데이트(double)의 세 가지 입력을 받습니다.주어진 주식 이름으로
StockTicker를 생성합니다. 이름이"Alice"인DayTrader와 이름이"Bob"인LongTermInvestor를 생성하고, 두 사람 모두 티커에 구독시킵니다.가격을 첫 번째 입력값으로 설정합니다 (모든 옵저버가 알림을 받습니다). 그런 다음 Alice를 구독 해지(unsubscribe)합니다. 마지막으로 가격을 두 번째 입력값으로 설정합니다 (이번에는 Bob만 알림을 받아야 합니다).
입력은 주식 이름(String), 첫 번째 가격(double), 두 번째 가격(double) 순서로 세 개가 주어집니다.
이 챌린지는 옵저버 패턴의 강력함을 보여줍니다. StockTicker는 구체적인 투자자 유형에 대해 알 필요가 없으며, 단지 그들이 Observer를 구현했다는 사실만 알면 됩니다. Alice를 구독 해지하면 그녀는 업데이트를 받지 않게 되지만, Bob은 계속해서 알림을 받습니다. 이러한 느슨한 결합(loose coupling) 덕분에 티커를 수정하지 않고도 새로운 투자자 유형을 쉽게 추가할 수 있습니다!
치트 시트
옵저버 패턴(Observer Pattern)은 객체 간의 일대다(one-to-many) 관계를 설정하는 행동 디자인 패턴입니다. 한 객체(주체(subject))의 상태가 변경되면, 그에 의존하는 모든 객체(옵저버(observers))들이 자동으로 알림을 받고 업데이트됩니다.
이 패턴은 두 가지 주요 구성 요소로 이루어집니다:
- 주체(Subject): 옵저버 목록을 유지하고 변경 사항을 알립니다.
- 옵저버(Observers): 알림에 응답하기 위한 업데이트 메서드를 정의합니다.
기본 구조:
import java.util.ArrayList;
import java.util.List;
interface Observer {
void update(String message);
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void subscribe(Observer observer) {
observers.add(observer);
}
public void unsubscribe(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
class ConcreteObserver implements Observer {
public void update(String message) {
// 알림에 반응
}
}사용 예시:
Subject subject = new Subject();
subject.subscribe(new ConcreteObserver());
subject.notifyObservers("State changed!");
// 구독된 모든 옵저버가 업데이트를 받습니다옵저버 패턴은 느슨한 결합(loose coupling)을 촉진합니다. 주체는 옵저버의 구체적인 클래스를 알 필요가 없으며, 단지 그들이 Observer 인터페이스를 구현한다는 사실만 알면 됩니다. 이를 통해 주체를 수정하지 않고도 새로운 옵저버 유형을 쉽게 추가할 수 있습니다.
직접 해보기
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 입력 읽기
String stockName = scanner.nextLine();
double firstPrice = scanner.nextDouble();
double secondPrice = scanner.nextDouble();
// TODO: 주어진 stock name으로 StockTicker 생성
// TODO: 이름이 "Alice"인 DayTrader 생성
// TODO: 이름이 "Bob"인 LongTermInvestor 생성
// TODO: Alice와 Bob 둘 다 ticker에 구독시키기
// TODO: 가격을 firstPrice로 설정 (두 관찰자 모두 알림을 받음)
// TODO: Alice 구독 해제
// TODO: 가격을 secondPrice로 설정 (Bob만 알림을 받음)
scanner.close();
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
4상속
상속의 기초 (extends)super 키워드메서드 오버라이딩 (@Override)생성자 체이닝Object 클래스단일 및 다중 레벨 상속다중 클래스 상속이 불가능한 이유요약 - 직원 계층 구조