Observerパターン
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 73/91。
Observer Patternは、オブジェクト間に一対多の関係を確立する振る舞いデザインパターンです。1つのオブジェクト(subject)の状態が変化すると、そのすべての依存オブジェクト(observers)に自動的に通知され、更新されます。
newsletter の購読について考えてみましょう。newsletter は subject であり、購読者は observer です。新しい号が発行されると、newsletter は各購読者の詳細を知る必要なく、すべての購読者が自動的にそれを受け取ります。
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とそのobserversを分離します。Newsletterクラスは、emailの購読者、SMSの購読者、またはプッシュ通知サービスのいずれに通知しているのかを知る必要がありません。Observerインターフェースをimplementsする対象に対して、単にupdate()を呼び出します。これにより、既存のコードを変更せずに新しいobserverの種類を簡単に追加できます。
チャレンジ
簡単Observer Pattern を使用して株価アラートシステムを構築しましょう。株価が変化すると、登録されているすべての Investors に自動的に通知されます。これは、このパターンの現実世界における完璧な適用例です。
コードを4つのファイルに分けて整理します。
Observer.php:単一のメソッドupdate(string $stockName, float $price): voidを持つObserverinterface を Define します。これは、notifications を受け取るためにすべての observers が従う必要がある契約です。Investors.php:Observer ファイルを Include し、interface を implements する2つの 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 ファイルを Include し、subject として acts するStockclass を Create します。Stock は次のようにします。- stock name と current price を保存します(name には constructor promotion を使用し、price を
0.0に Initialize します) - observers の private array を Maintain します
- observers を追加する
subscribe(Observer $observer): voidmethod を持たせます - price を更新し、すべての observers に notify する
setPrice(float $price): voidmethod を持たせます
update()method を stock name と new price とともに Call します。- stock name と current price を保存します(name には constructor promotion を使用し、price を
main.php:Investors ファイルと Stock ファイルを Include します。3つの inputs、つまり stock name、email address、phone number を受け取ります。given name で
Stockを Create します。email address を持つEmailInvestorと、phone number を持つSmsInvestorを subscribe します。すべての subscribers への notifications を trigger するため、stock price を
150.50に設定します。
Observer Pattern により、Stock class は具体的な notification methods から decoupled になります。Stock class をまったく変更せずに、後から簡単に PushInvestor や SlackInvestor を追加できます。
自分で試してみよう
<?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に設定して通知をトリガーする
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: PHPオンラインコンパイラ