PHP设计模式装饰器与代理实践

PHP设计模式装饰器与代理实践 PHP设计模式装饰器与代理实践装饰器模式和代理模式在结构上有些相似但目的完全不同。装饰器动态添加功能代理控制访问。今天用实际代码说明两者的区别。装饰器模式的核心是层层包装每个装饰器添加一点功能。phpinterface NotificationInterface{public function send(string $message): void;}class BasicNotification implements NotificationInterface{public function send(string $message): void{echo 发送消息: $message\n;}}abstract class NotificationDecorator implements NotificationInterface{protected NotificationInterface $notification;public function __construct(NotificationInterface $notification){$this-notification $notification;}}class EmailDecorator extends NotificationDecorator{private string $email;public function __construct(NotificationInterface $notification, string $email){parent::__construct($notification);$this-email $email;}public function send(string $message): void{$this-notification-send($message);echo 发送邮件至 {$this-email}: $message\n;}}class SmsDecorator extends NotificationDecorator{private string $phone;public function __construct(NotificationInterface $notification, string $phone){parent::__construct($notification);$this-phone $phone;}public function send(string $message): void{$this-notification-send($message);echo 发送短信至 {$this-phone}: $message\n;}}class SlackDecorator extends NotificationDecorator{private string $channel;public function __construct(NotificationInterface $notification, string $channel){parent::__construct($notification);$this-channel $channel;}public function send(string $message): void{$this-notification-send($message);echo 发送Slack消息到 {$this-channel}: $message\n;}}class LogDecorator extends NotificationDecorator{public function send(string $message): void{echo [日志] 开始发送通知\n;$this-notification-send($message);echo [日志] 通知发送完成\n;}}$notification new BasicNotification();$notification new EmailDecorator($notification, userexample.com);$notification new SmsDecorator($notification, 13800138000);$notification new SlackDecorator($notification, #general);$notification new LogDecorator($notification);$notification-send(系统更新通知);?代理模式在需要控制对对象的访问时使用。常见的代理类型有虚拟代理、保护代理、远程代理等。phpinterface ImageInterface{public function display(): void;public function getSize(): array;}class RealImage implements ImageInterface{private string $filename;private int $width;private int $height;public function __construct(string $filename){$this-filename $filename;$this-loadFromDisk();}private function loadFromDisk(): void{echo 从磁盘加载图片: {$this-filename}\n;$this-width 1920;$this-height 1080;}public function display(): void{echo 显示图片: {$this-filename} ({$this-width}x{$this-height})\n;}public function getSize(): array{return [width $this-width, height $this-height];}}class ImageProxy implements ImageInterface{private ?RealImage $realImage null;private int $accessCount 0;public function __construct(private string $filename) {}public function display(): void{$this-accessCount;echo 代理记录: 第{$this-accessCount}次访问\n;if ($this-realImage null) {$this-realImage new RealImage($this-filename);}$this-realImage-display();}public function getSize(): array{if ($this-realImage null) {return [width 0, height 0, note 图片尚未加载];}return $this-realImage-getSize();}public function getAccessCount(): int{return $this-accessCount;}}$image new ImageProxy(photo.jpg);echo 图片信息: . json_encode($image-getSize()) . \n;$image-display();$image-display();echo 访问次数: {$image-getAccessCount()}\n;?保护代理控制访问权限phpinterface DocumentInterface{public function getContent(): string;public function getMetadata(): array;}class Document implements DocumentInterface{public function __construct(private int $id,private string $content,private array $metadata []) {}public function getContent(): string{return $this-content;}public function getMetadata(): array{return $this-metadata;}}class DocumentProxy implements DocumentInterface{private ?Document $document null;private array $permissions;public function __construct(int $id,string $content,private string $owner,array $permissions []) {$this-permissions $permissions;$this-document new Document($id, $content, [owner $owner]);}public function getContent(): string{if (!$this-hasPermission(read)) {throw new RuntimeException(没有读取权限);}return $this-document-getContent();}public function getMetadata(): array{return $this-document-getMetadata();}public function setPermission(string $user, string $perm): void{if ($user $this-owner) {$this-permissions[$user][] $perm;}}private function hasPermission(string $perm): bool{$userPerms $this-permissions[$this-owner] ?? [];return in_array($perm, $userPerms);}}$doc new DocumentProxy(1, 机密内容, 张三, [张三 [read]]);echo $doc-getMetadata()[owner] . 的文档\n;echo $doc-getContent() . \n;?装饰器和代理的主要区别是用途不同。装饰器用于增强功能代理用于控制访问。在实现上装饰器通常接收被装饰对象作为构造参数代理则自己创建或引用目标对象。理解了这两种模式的区别在实际项目中就能根据需求选择合适的方案。