Menu
Coddy logo textTech

옵서버 패턴

Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 91개 중 73번째.

Observer Pattern은 객체 간에 일대다 관계를 설정하는 행동 디자인 패턴입니다. 한 객체(subject)의 상태가 변경되면 해당 객체에 의존하는 모든 객체(observers)에 자동으로 알림이 전달되고 업데이트됩니다.

뉴스레터 구독을 생각해 보세요. 뉴스레터는 주제이고, 구독자는 옵저버입니다. 새 호가 발행되면 뉴스레터가 각 구독자의 세부 정보를 알 필요 없이 모든 구독자가 자동으로 이를 받습니다.

PHP로 구현한 기본 예시는 다음과 같습니다:

<?php
interface Observer {
    public function update(string $message): void;
}

class Newsletter {
    private array $subscribers = [];
    
    public function subscribe(Observer $observer): void {
        $this->subscribers[] = $observer;
    }
    
    public function publish(string $content): void {
        foreach ($this->subscribers as $subscriber) {
            $subscriber->update($content);
        }
    }
}

class EmailSubscriber implements Observer {
    public function __construct(private string $email) {}
    
    public function update(string $message): void {
        echo "Sending to {$this->email}: $message\n";
    }
}

$newsletter = new Newsletter();
$newsletter->subscribe(new EmailSubscriber("alice@example.com"));
$newsletter->subscribe(new EmailSubscriber("bob@example.com"));
$newsletter->publish("New article released!");

출력:

Sending to alice@example.com: New article released!
Sending to bob@example.com: New article released!

이 패턴은 subject와 해당 observer를 분리합니다. Newsletter 클래스는 이메일 구독자, SMS 구독자 또는 푸시 알림 서비스를 Notifying하는지 알 필요가 없습니다. 단순히 Observer interface를 Implement하는 모든 대상에서 update()를 Call합니다. 따라서 기존 코드를 수정하지 않고도 새로운 observer 유형을 손쉽게 추가할 수 있습니다.

challenge icon

챌린지

쉬움

Observer Pattern을 사용하여 주가 알림 시스템을 만들어 봅시다. 주식의 가격이 변경되면 등록된 모든 Investors에게 자동으로 알림이 전송됩니다. 이는 이 패턴을 실제 세계에 적용한 완벽한 예입니다.

코드를 네 개의 파일로 구성합니다:

  • Observer.php: 하나의 Observer interface와 단일 update(string $stockName, float $price): void method를 Define합니다. 이는 알림을 받기 위해 모든 observers가 따라야 하는 계약입니다.
  • Investors.php: Observer 파일을 포함하고 interface를 implements하는 두 개의 class를 Create합니다:
    • EmailInvestor: constructor에서 email address를 받습니다(constructor promotion 사용). 해당 update() method는 "Email to [email]: [stockName] is now $[price]"를 출력합니다.
    • SmsInvestor: constructor에서 phone number를 받습니다. 해당 update() method는 "SMS to [phone]: [stockName] is now $[price]"를 출력합니다.
  • Stock.php: Observer 파일을 포함하고 subject 역할을 하는 Stock class를 Create합니다. Stock은 다음을 수행해야 합니다:
    • stock name과 current price를 저장합니다(name에는 constructor promotion을 사용하고, price를 0.0으로 Initialize).
    • observers의 private array를 Maintain합니다.
    • observers를 Add하기 위한 subscribe(Observer $observer): void method를 가집니다.
    • price를 업데이트하고 모든 observers에게 알림을 보내는 setPrice(float $price): void method를 가집니다.
    observers에게 알림을 보낼 때는 각 observer의 update() method를 stock name과 new price와 함께 Call합니다.
  • main.php: Investors 및 Stock 파일을 포함합니다. 세 가지 inputs를 받습니다: stock name, email address, phone number.

    given name으로 Stock을 Create합니다. email address를 사용하여 EmailInvestor를, phone number를 사용하여 SmsInvestor를 subscribe합니다.

    모든 subscribers에게 알림을 trigger하도록 stock price를 150.50으로 설정합니다.

Observer Pattern은 Stock class를 특정 알림 method와 decoupled 상태로 유지합니다. 나중에 Stock class를 전혀 수정하지 않고도 PushInvestor 또는 SlackInvestor를 쉽게 Add할 수 있습니다.

직접 해보기

<?php
require_once 'Investors.php';
require_once 'Stock.php';

// 입력 읽기
$stockName = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$phone = trim(fgets(STDIN));

// TODO: 주어진 이름으로 Stock 생성

// TODO: 이메일 주소로 EmailInvestor 구독

// TODO: 전화번호로 SmsInvestor 구독

// TODO: 알림을 트리거하기 위해 주식 가격을 150.50으로 설정
?>
quiz icon실력 점검

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

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

직접 연습해 보세요: 온라인 PHP 컴파일러