本文目录导读:

我来详细讲解PHP中观察者模式的实现,包括基础实现和实际应用场景。
基础观察者模式实现
观察者接口
<?php
// 观察者接口
interface Observer {
public function update(string $event, mixed $data = null): void;
}
// 主题接口(被观察者)
interface Subject {
public function attach(Observer $observer): void;
public function detach(Observer $observer): void;
public function notify(string $event, mixed $data = null): void;
}
具体主题类
<?php
class EventManager implements Subject {
private array $observers = [];
private array $events = [];
public function attach(Observer $observer): void {
// 使用SplObjectStorage存储,避免重复添加
if (!in_array($observer, $this->observers, true)) {
$this->observers[] = $observer;
}
}
public function detach(Observer $observer): void {
$key = array_search($observer, $this->observers, true);
if ($key !== false) {
unset($this->observers[$key]);
$this->observers = array_values($this->observers);
}
}
public function notify(string $event, mixed $data = null): void {
foreach ($this->observers as $observer) {
$observer->update($event, $data);
}
}
// 按事件分类通知
public function notifyByEvent(string $event, mixed $data = null): void {
foreach ($this->observers as $observer) {
if ($observer->canHandle($event)) {
$observer->update($event, $data);
}
}
}
}
具体观察者
<?php
class EmailNotifier implements Observer {
private string $email;
public function __construct(string $email) {
$this->email = $email;
}
public function update(string $event, mixed $data = null): void {
echo "发送邮件到 {$this->email}:发生了事件 {$event}\n";
if ($data) {
echo "事件数据: " . json_encode($data) . "\n";
}
}
public function canHandle(string $event): bool {
return in_array($event, ['user.registered', 'password.reset']);
}
}
class LogObserver implements Observer {
private string $logFile;
public function __construct(string $logFile = 'app.log') {
$this->logFile = $logFile;
}
public function update(string $event, mixed $data = null): void {
$logEntry = sprintf(
"[%s] Event: %s, Data: %s\n",
date('Y-m-d H:i:s'),
$event,
json_encode($data)
);
file_put_contents($this->logFile, $logEntry, FILE_APPEND);
}
public function canHandle(string $event): bool {
return true; // 记录所有事件
}
}
class MetricsCollector implements Observer {
private array $metrics = [];
public function update(string $event, mixed $data = null): void {
if (!isset($this->metrics[$event])) {
$this->metrics[$event] = 0;
}
$this->metrics[$event]++;
echo "指标统计: {$event} 发生次数: {$this->metrics[$event]}\n";
}
public function canHandle(string $event): bool {
return true;
}
public function getMetrics(): array {
return $this->metrics;
}
}
使用示例
<?php
// 使用示例
$eventManager = new EventManager();
// 创建观察者
$emailNotifier = new EmailNotifier('admin@example.com');
$logObserver = new LogObserver('/tmp/app.log');
$metrics = new MetricsCollector();
// 注册观察者
$eventManager->attach($emailNotifier);
$eventManager->attach($logObserver);
$eventManager->attach($metrics);
// 触发事件
$eventManager->notify('user.registered', [
'user_id' => 1,
'email' => 'user@example.com',
'created_at' => date('Y-m-d H:i:s')
]);
$eventManager->notify('user.login', [
'user_id' => 1,
'login_time' => date('Y-m-d H:i:s')
]);
// 移除观察者
$eventManager->detach($emailNotifier);
$eventManager->notify('user.logout', ['user_id' => 1]);
PHP内置的SplObserver实现
<?php
// 使用PHP内置接口
class User implements SplSubject {
private SplObjectStorage $observers;
private array $userData;
public function __construct() {
$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 setUserData(array $data): void {
$this->userData = $data;
$this->notify();
}
public function getUserData(): array {
return $this->userData;
}
}
class UserObserver implements SplObserver {
private string $name;
public function __construct(string $name) {
$this->name = $name;
}
public function update(SplSubject $subject): void {
if ($subject instanceof User) {
echo "观察者 {$this->name} 收到更新:";
echo json_encode($subject->getUserData()) . "\n";
}
}
}
// 使用SplObserver
$user = new User();
$observer1 = new UserObserver('观察者A');
$observer2 = new UserObserver('观察者B');
$user->attach($observer1);
$user->attach($observer2);
$user->setUserData(['name' => '张三', 'age' => 25]);
实际应用场景:订单系统
<?php
// 订单事件观察者模式
interface OrderObserver {
public function onOrderCreated(Order $order): void;
public function onOrderPaid(Order $order): void;
public function onOrderCanceled(Order $order): void;
}
// 订单类
class Order {
private array $observers = [];
private array $orderData;
public function __construct(array $orderData) {
$this->orderData = $orderData;
}
public function attach(OrderObserver $observer): void {
$this->observers[] = $observer;
}
public function detach(OrderObserver $observer): void {
$key = array_search($observer, $this->observers, true);
if ($key !== false) {
unset($this->observers[$key]);
}
}
public function create(): void {
echo "订单已创建\n";
$this->notify('onOrderCreated');
}
public function pay(): void {
$this->orderData['status'] = 'paid';
echo "订单已支付\n";
$this->notify('onOrderPaid');
}
public function cancel(): void {
$this->orderData['status'] = 'canceled';
echo "订单已取消\n";
$this->notify('onOrderCanceled');
}
private function notify(string $method): void {
foreach ($this->observers as $observer) {
$observer->$method($this);
}
}
public function getOrderData(): array {
return $this->orderData;
}
}
// 实际业务观察者
class InventoryService implements OrderObserver {
public function onOrderCreated(Order $order): void {
echo "库存系统:锁定商品库存\n";
}
public function onOrderPaid(Order $order): void {
echo "库存系统:扣减库存\n";
}
public function onOrderCanceled(Order $order): void {
echo "库存系统:释放库存\n";
}
}
class PaymentService implements OrderObserver {
public function onOrderCreated(Order $order): void {
// 不处理
}
public function onOrderPaid(Order $order): void {
echo "支付系统:处理支付结果\n";
}
public function onOrderCanceled(Order $order): void {
echo "支付系统:处理退款\n";
}
}
class NotificationService implements OrderObserver {
public function onOrderCreated(Order $order): void {
echo "通知系统:发送订单创建通知\n";
}
public function onOrderPaid(Order $order): void {
echo "通知系统:发送支付成功通知\n";
}
public function onOrderCanceled(Order $order): void {
echo "通知系统:发送订单取消通知\n";
}
}
// 使用订单系统
$order = new Order([
'id' => 'ORD001',
'product_name' => 'iPhone 15',
'price' => 7999,
'status' => 'pending'
]);
// 注册观察者
$order->attach(new InventoryService());
$order->attach(new PaymentService());
$order->attach(new NotificationService());
// 业务流程
$order->create();
$order->pay();
// $order->cancel(); // 取消流程
事件分发器实现
<?php
class EventDispatcher {
private array $listeners = [];
// 添加事件监听器
public function addListener(string $eventName, callable $listener, int $priority = 0): void {
$this->listeners[$eventName][$priority][] = $listener;
ksort($this->listeners[$eventName]);
}
// 触发事件
public function dispatch(string $eventName, array $payload = []): void {
if (!isset($this->listeners[$eventName])) {
return;
}
foreach ($this->listeners[$eventName] as $priorityListeners) {
foreach ($priorityListeners as $listener) {
call_user_func_array($listener, [$payload, $eventName]);
}
}
}
// 移除监听器
public function removeListener(string $eventName, callable $listener): void {
if (!isset($this->listeners[$eventName])) {
return;
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $key => $existingListener) {
if ($existingListener === $listener) {
unset($this->listeners[$eventName][$priority][$key]);
}
}
}
}
}
// 使用事件分发器
$dispatcher = new EventDispatcher();
// 注册事件
$dispatcher->addListener('user.register', function($data) {
echo "发送注册邮件: " . $data['email'] . "\n";
}, 10);
$dispatcher->addListener('user.register', function($data) {
echo "记录注册日志\n";
}, 5);
$dispatcher->addListener('user.login', function($data) {
echo "用户 {$data['username']} 登录成功\n";
}, 1);
// 触发事件
$dispatcher->dispatch('user.register', ['email' => 'test@example.com', 'username' => '张三']);
$dispatcher->dispatch('user.login', ['username' => '张三']);
注意事项和最佳实践
<?php
// 1. 使用事件类封装数据
final class OrderCreated {
public function __construct(
public readonly Order $order,
public readonly array $metadata = []
) {}
}
// 2. 观察者注册管理
class EventManager {
private static ?EventManager $instance = null;
private array $observers = [];
public static function getInstance(): EventManager {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// 防止克隆
private function __clone() {}
public function register(string $event, callable $callback, int $priority = 0): void {
$this->observers[$event][] = [
'callback' => $callback,
'priority' => $priority
];
// 按优先级排序
usort($this->observers[$event], function($a, $b) {
return $b['priority'] <=> $a['priority'];
});
}
public function trigger(string $event, array $data = []): void {
if (!isset($this->observers[$event])) {
return;
}
foreach ($this->observers[$event] as $observer) {
call_user_func($observer['callback'], $data, $event);
}
}
}
// 使用单例模式
$eventManager = EventManager::getInstance();
$eventManager->register('product.low_stock', function($data) {
echo "商品库存不足: " . $data['product_id'] . "\n";
// 发送邮件通知
}, 100);
$eventManager->trigger('product.low_stock', ['product_id' => 5, 'current' => 2]);
与框架集成示例(Laravel风格)
<?php
// 事件类
class OrderShipped {
public function __construct(
public Order $order,
public string $shippedAt
) {}
}
// 监听器
class UpdateInventory {
public function handle(OrderShipped $event): void {
// 更新库存逻辑
echo "更新库存:" . $event->order->id . "\n";
}
}
// 事件监听器注册(通常在EventServiceProvider中)
$eventListeners = [
OrderShipped::class => [
UpdateInventory::class,
SendOrderNotification::class,
RecordTracking::class,
],
];
// 简单的事件分发器实现
class EventServiceProvider {
private array $listeners = [];
public function register(array $listeners): void {
foreach ($listeners as $event => $eventListeners) {
foreach ($eventListeners as $listener) {
$this->listeners[$event][] = new $listener();
}
}
}
public function dispatch(object $event): void {
$eventClass = get_class($event);
if (!isset($this->listeners[$eventClass])) {
return;
}
foreach ($this->listeners[$eventClass] as $listener) {
$listener->handle($event);
}
}
}
// 使用
$provider = new EventServiceProvider();
$provider->register($eventListeners);
$event = new OrderShipped(new Order(['id' => 1]), date('Y-m-d H:i:s'));
$provider->dispatch($event);
观察者模式的优势:
- 解耦:主题和观察者之间松耦合
- 扩展性:轻松添加新的观察者
- 一致性:当状态变化时自动通知所有依赖者
- 复用性:观察者可以被多个主题使用
在实际开发中,建议:
- 使用事件类封装事件数据
- 考虑事件优先级
- 实现事件撤销机制(如果必要)
- 合理的性能优化(异步处理等)
- 严格遵守单一职责原则
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播