PHP设计模式观察者与中介者实现观察者模式和中介者模式都是用于对象间通信的设计模式。观察者模式实现一对多的依赖关系中介者模式减少多对多的直接通信。今天用实际代码说明这两种模式。观察者模式的核心是当一个对象状态变化时所有依赖它的对象都得到通知。PHP的SPL提供了SplSubject和SplObserver接口。php// 订单状态变更的事件系统class Order implements SplSubject{private SplObjectStorage $observers;private array $data;public function __construct(array $data){$this-data $data;$this-observers new SplObjectStorage();}public function attach(SplObserver $observer): void{$this-observers-attach($observer);}public function detach(SplObserver $observer): void{$this-observers-detach($observer);}public function notify(): void{foreach ($this-observers as $observer) {$observer-update($this);}}public function setStatus(string $status): void{$oldStatus $this-data[status] ?? unknown;$this-data[status] $status;echo 订单 {$this-data[id]} 状态变更: $oldStatus - $status\n;$this-notify();}public function getData(): array{return $this-data;}}class EmailNotifier implements SplObserver{public function update(SplSubject $subject): void{if (!$subject instanceof Order) return;$data $subject-getData();$messages [paid 订单 {$data[id]} 已支付发送确认邮件,shipped 订单 {$data[id]} 已发货发送物流通知,cancelled 订单 {$data[id]} 已取消发送退款通知,];if (isset($messages[$data[status]])) {echo [邮件] {$messages[$data[status]]}\n;}}}class SmsNotifier implements SplObserver{public function update(SplSubject $subject): void{if (!$subject instanceof Order) return;$data $subject-getData();if ($data[status] shipped) {echo [短信] 订单 {$data[id]} 已发货通知用户\n;}}}class InventoryUpdater implements SplObserver{public function update(SplSubject $subject): void{if (!$subject instanceof Order) return;$data $subject-getData();if ($data[status] paid) {echo [库存] 订单 {$data[id]} 扣减库存\n;} elseif ($data[status] cancelled) {echo [库存] 订单 {$data[id]} 恢复库存\n;}}}class LoggerObserver implements SplObserver{public function update(SplSubject $subject): void{if (!$subject instanceof Order) return;$data $subject-getData();echo [日志] 订单 {$data[id]} 状态: {$data[status]}\n;}}// 使用$order new Order([id ORD-2024-0001, amount 299.00]);$order-attach(new EmailNotifier());$order-attach(new SmsNotifier());$order-attach(new InventoryUpdater());$order-attach(new LoggerObserver());$order-setStatus(paid);$order-setStatus(shipped);?中介者模式减少对象之间的直接通信通过中介者协调交互。聊天室是一个经典的例子。phpinterface ChatMediator{public function sendMessage(User $sender, string $message): void;public function sendPrivateMessage(User $sender, User $recipient, string $message): void;public function addUser(User $user): void;public function removeUser(User $user): void;}class ChatRoom implements ChatMediator{private array $users [];private array $messageHistory [];public function addUser(User $user): void{$this-users[$user-getName()] $user;$user-setMediator($this);$this-broadcastSystemMessage({$user-getName()} 加入了聊天室);}public function removeUser(User $user): void{unset($this-users[$user-getName()]);$this-broadcastSystemMessage({$user-getName()} 离开了聊天室);}public function sendMessage(User $sender, string $message): void{$this-messageHistory[] [from $sender-getName(),message $message,time date(H:i:s),type public,];foreach ($this-users as $name $user) {if ($user ! $sender) {$user-receive($sender-getName(), $message);}}}public function sendPrivateMessage(User $sender, User $recipient, string $message): void{$this-messageHistory[] [from $sender-getName(),to $recipient-getName(),message $message,time date(H:i:s),type private,];$recipient-receivePrivate($sender-getName(), $message);$sender-notify(私信已发送给 {$recipient-getName()});}private function broadcastSystemMessage(string $message): void{foreach ($this-users as $user) {$user-receiveSystem($message);}}public function getMessageHistory(): array{return $this-messageHistory;}}class User{private ?ChatMediator $mediator null;public function __construct(private string $name) {}public function setMediator(ChatMediator $mediator): void{$this-mediator $mediator;}public function getName(): string{return $this-name;}public function send(string $message): void{echo {$this-name} 发送: $message\n;$this-mediator-sendMessage($this, $message);}public function sendPrivate(User $recipient, string $message): void{echo {$this-name} 私信 {$recipient-getName()}: $message\n;$this-mediator-sendPrivateMessage($this, $recipient, $message);}public function receive(string $from, string $message): void{echo [{$this-name}] {$from}: $message\n;}public function receivePrivate(string $from, string $message): void{echo [{$this-name}] (私信) {$from}: $message\n;}public function receiveSystem(string $message): void{echo [{$this-name}] (系统) $message\n;}public function notify(string $message): void{echo [{$this-name}] $message\n;}}$chatRoom new ChatRoom();$alice new User(Alice);$bob new User(Bob);$charlie new User(Charlie);$chatRoom-addUser($alice);$chatRoom-addUser($bob);$chatRoom-addUser($charlie);echo \n;$alice-send(大家好);echo \n;$bob-send(Alice你好);echo \n;$charlie-sendPrivate($alice, 晚上一起吃饭吗);echo \n;$chatRoom-removeUser($charlie);?中介者模式在UI组件之间协调时也很常用。比如表单中各个字段的联动。phpinterface FormMediator{public function notify(FormComponent $sender, string $event, mixed $data null): void;}class FormComponent{protected ?FormMediator $mediator null;public function __construct(protected string $name) {}public function setMediator(FormMediator $mediator): void{$this-mediator $mediator;}public function getName(): string{return $this-name;}}class SelectField extends FormComponent{private string $value ;private array $options [];public function setOptions(array $options): void{$this-options $options;}public function setValue(string $value): void{$this-value $value;echo 选择框 {$this-name} 选择: $value\n;if ($this-mediator) {$this-mediator-notify($this, change, $value);}}public function getValue(): string{return $this-value;}public function getOptions(): array{return $this-options;}}class InputField extends FormComponent{private string $value ;private bool $disabled false;public function setValue(string $value): void{$this-value $value;}public function getValue(): string{return $this-value;}public function setDisabled(bool $disabled): void{$this-disabled $disabled;echo 输入框 {$this-name} . ($disabled ? 禁用 : 启用) . \n;}}class SubmitButton extends FormComponent{private bool $enabled false;public function setEnabled(bool $enabled): void{$this-enabled $enabled;echo 提交按钮 . ($enabled ? 可用 : 不可用) . \n;}public function click(): void{if (!$this-enabled) {echo 按钮不可用\n;return;}echo 表单提交!\n;if ($this-mediator) {$this-mediator-notify($this, submit);}}}class UserFormMediator implements FormMediator{private SelectField $countrySelect;private InputField $cityInput;private InputField $phoneInput;private SubmitButton $submitButton;public function __construct(){$this-countrySelect new SelectField(country);$this-cityInput new InputField(city);$this-phoneInput new InputField(phone);$this-submitButton new SubmitButton(submit);$this-countrySelect-setMediator($this);$this-cityInput-setMediator($this);$this-phoneInput-setMediator($this);$this-submitButton-setMediator($this);$this-countrySelect-setOptions([, 中国, 美国, 日本]);$this-cityInput-setDisabled(true);}public function notify(FormComponent $sender, string $event, mixed $data null): void{if ($sender $this-countrySelect $event change) {if (empty($data)) {$this-cityInput-setDisabled(true);$this-cityInput-setValue();$this-phoneInput-setDisabled(true);$this-phoneInput-setValue();$this-submitButton-setEnabled(false);} else {$this-cityInput-setDisabled(false);$this-phoneInput-setDisabled(false);$this-submitButton-setEnabled(true);}}}public function getCountrySelect(): SelectField { return $this-countrySelect; }public function getCityInput(): InputField { return $this-cityInput; }public function getPhoneInput(): InputField { return $this-phoneInput; }public function getSubmitButton(): SubmitButton { return $this-submitButton; }}$mediator new UserFormMediator();$mediator-getCountrySelect()-setValue(中国);$mediator-getSubmitButton()-click();?观察者模式适合一对多的通知场景中介者模式适合多对多的协调场景。两种模式都能降低对象之间的耦合度让系统更容易维护和扩展。
PHP设计模式观察者与中介者实现
PHP设计模式观察者与中介者实现观察者模式和中介者模式都是用于对象间通信的设计模式。观察者模式实现一对多的依赖关系中介者模式减少多对多的直接通信。今天用实际代码说明这两种模式。观察者模式的核心是当一个对象状态变化时所有依赖它的对象都得到通知。PHP的SPL提供了SplSubject和SplObserver接口。php// 订单状态变更的事件系统class Order implements SplSubject{private SplObjectStorage $observers;private array $data;public function __construct(array $data){$this-data $data;$this-observers new SplObjectStorage();}public function attach(SplObserver $observer): void{$this-observers-attach($observer);}public function detach(SplObserver $observer): void{$this-observers-detach($observer);}public function notify(): void{foreach ($this-observers as $observer) {$observer-update($this);}}public function setStatus(string $status): void{$oldStatus $this-data[status] ?? unknown;$this-data[status] $status;echo 订单 {$this-data[id]} 状态变更: $oldStatus - $status\n;$this-notify();}public function getData(): array{return $this-data;}}class EmailNotifier implements SplObserver{public function update(SplSubject $subject): void{if (!$subject instanceof Order) return;$data $subject-getData();$messages [paid 订单 {$data[id]} 已支付发送确认邮件,shipped 订单 {$data[id]} 已发货发送物流通知,cancelled 订单 {$data[id]} 已取消发送退款通知,];if (isset($messages[$data[status]])) {echo [邮件] {$messages[$data[status]]}\n;}}}class SmsNotifier implements SplObserver{public function update(SplSubject $subject): void{if (!$subject instanceof Order) return;$data $subject-getData();if ($data[status] shipped) {echo [短信] 订单 {$data[id]} 已发货通知用户\n;}}}class InventoryUpdater implements SplObserver{public function update(SplSubject $subject): void{if (!$subject instanceof Order) return;$data $subject-getData();if ($data[status] paid) {echo [库存] 订单 {$data[id]} 扣减库存\n;} elseif ($data[status] cancelled) {echo [库存] 订单 {$data[id]} 恢复库存\n;}}}class LoggerObserver implements SplObserver{public function update(SplSubject $subject): void{if (!$subject instanceof Order) return;$data $subject-getData();echo [日志] 订单 {$data[id]} 状态: {$data[status]}\n;}}// 使用$order new Order([id ORD-2024-0001, amount 299.00]);$order-attach(new EmailNotifier());$order-attach(new SmsNotifier());$order-attach(new InventoryUpdater());$order-attach(new LoggerObserver());$order-setStatus(paid);$order-setStatus(shipped);?中介者模式减少对象之间的直接通信通过中介者协调交互。聊天室是一个经典的例子。phpinterface ChatMediator{public function sendMessage(User $sender, string $message): void;public function sendPrivateMessage(User $sender, User $recipient, string $message): void;public function addUser(User $user): void;public function removeUser(User $user): void;}class ChatRoom implements ChatMediator{private array $users [];private array $messageHistory [];public function addUser(User $user): void{$this-users[$user-getName()] $user;$user-setMediator($this);$this-broadcastSystemMessage({$user-getName()} 加入了聊天室);}public function removeUser(User $user): void{unset($this-users[$user-getName()]);$this-broadcastSystemMessage({$user-getName()} 离开了聊天室);}public function sendMessage(User $sender, string $message): void{$this-messageHistory[] [from $sender-getName(),message $message,time date(H:i:s),type public,];foreach ($this-users as $name $user) {if ($user ! $sender) {$user-receive($sender-getName(), $message);}}}public function sendPrivateMessage(User $sender, User $recipient, string $message): void{$this-messageHistory[] [from $sender-getName(),to $recipient-getName(),message $message,time date(H:i:s),type private,];$recipient-receivePrivate($sender-getName(), $message);$sender-notify(私信已发送给 {$recipient-getName()});}private function broadcastSystemMessage(string $message): void{foreach ($this-users as $user) {$user-receiveSystem($message);}}public function getMessageHistory(): array{return $this-messageHistory;}}class User{private ?ChatMediator $mediator null;public function __construct(private string $name) {}public function setMediator(ChatMediator $mediator): void{$this-mediator $mediator;}public function getName(): string{return $this-name;}public function send(string $message): void{echo {$this-name} 发送: $message\n;$this-mediator-sendMessage($this, $message);}public function sendPrivate(User $recipient, string $message): void{echo {$this-name} 私信 {$recipient-getName()}: $message\n;$this-mediator-sendPrivateMessage($this, $recipient, $message);}public function receive(string $from, string $message): void{echo [{$this-name}] {$from}: $message\n;}public function receivePrivate(string $from, string $message): void{echo [{$this-name}] (私信) {$from}: $message\n;}public function receiveSystem(string $message): void{echo [{$this-name}] (系统) $message\n;}public function notify(string $message): void{echo [{$this-name}] $message\n;}}$chatRoom new ChatRoom();$alice new User(Alice);$bob new User(Bob);$charlie new User(Charlie);$chatRoom-addUser($alice);$chatRoom-addUser($bob);$chatRoom-addUser($charlie);echo \n;$alice-send(大家好);echo \n;$bob-send(Alice你好);echo \n;$charlie-sendPrivate($alice, 晚上一起吃饭吗);echo \n;$chatRoom-removeUser($charlie);?中介者模式在UI组件之间协调时也很常用。比如表单中各个字段的联动。phpinterface FormMediator{public function notify(FormComponent $sender, string $event, mixed $data null): void;}class FormComponent{protected ?FormMediator $mediator null;public function __construct(protected string $name) {}public function setMediator(FormMediator $mediator): void{$this-mediator $mediator;}public function getName(): string{return $this-name;}}class SelectField extends FormComponent{private string $value ;private array $options [];public function setOptions(array $options): void{$this-options $options;}public function setValue(string $value): void{$this-value $value;echo 选择框 {$this-name} 选择: $value\n;if ($this-mediator) {$this-mediator-notify($this, change, $value);}}public function getValue(): string{return $this-value;}public function getOptions(): array{return $this-options;}}class InputField extends FormComponent{private string $value ;private bool $disabled false;public function setValue(string $value): void{$this-value $value;}public function getValue(): string{return $this-value;}public function setDisabled(bool $disabled): void{$this-disabled $disabled;echo 输入框 {$this-name} . ($disabled ? 禁用 : 启用) . \n;}}class SubmitButton extends FormComponent{private bool $enabled false;public function setEnabled(bool $enabled): void{$this-enabled $enabled;echo 提交按钮 . ($enabled ? 可用 : 不可用) . \n;}public function click(): void{if (!$this-enabled) {echo 按钮不可用\n;return;}echo 表单提交!\n;if ($this-mediator) {$this-mediator-notify($this, submit);}}}class UserFormMediator implements FormMediator{private SelectField $countrySelect;private InputField $cityInput;private InputField $phoneInput;private SubmitButton $submitButton;public function __construct(){$this-countrySelect new SelectField(country);$this-cityInput new InputField(city);$this-phoneInput new InputField(phone);$this-submitButton new SubmitButton(submit);$this-countrySelect-setMediator($this);$this-cityInput-setMediator($this);$this-phoneInput-setMediator($this);$this-submitButton-setMediator($this);$this-countrySelect-setOptions([, 中国, 美国, 日本]);$this-cityInput-setDisabled(true);}public function notify(FormComponent $sender, string $event, mixed $data null): void{if ($sender $this-countrySelect $event change) {if (empty($data)) {$this-cityInput-setDisabled(true);$this-cityInput-setValue();$this-phoneInput-setDisabled(true);$this-phoneInput-setValue();$this-submitButton-setEnabled(false);} else {$this-cityInput-setDisabled(false);$this-phoneInput-setDisabled(false);$this-submitButton-setEnabled(true);}}}public function getCountrySelect(): SelectField { return $this-countrySelect; }public function getCityInput(): InputField { return $this-cityInput; }public function getPhoneInput(): InputField { return $this-phoneInput; }public function getSubmitButton(): SubmitButton { return $this-submitButton; }}$mediator new UserFormMediator();$mediator-getCountrySelect()-setValue(中国);$mediator-getSubmitButton()-click();?观察者模式适合一对多的通知场景中介者模式适合多对多的协调场景。两种模式都能降低对象之间的耦合度让系统更容易维护和扩展。