php 设计模式 七
装饰器模式
介绍
核心思想是使用组合而非继承来扩展对象的功能。
是一种结构型设计模式,允许你通过将对象放入包含行为的特殊封装对象中来为原对象动态添加新的行为。
用于获取原对象的类 A装饰类 装饰类1 B 装饰类2 C
$d = new A();$e = new B(new C(d));
适用情况
适合需要在运行时动态添加/撤销功能;功能组合的数量和方式很多,且不需要多重继承;符合开闭原则(对扩展开放,对修改关闭)的场景。
不适合需要添加的功能数量很少且固定;对象内部结构复杂,装饰成本高;需要访问被装饰对象的内部细节。
代码实现
用于获取原对象的类
// 组件接口interfaceDataSource{publicfunctionwrite(string $data): void;publicfunctionread(): string;}
// 具体组件:文件数据源classFileDataSourceimplementsDataSource{private string $filename;publicfunction__construct(string $filename){$this->filename = $filename; }publicfunctionwrite(string $data): void{ file_put_contents($this->filename, $data);echo"写入原始数据到文件\n"; }publicfunctionread(): string{ $content = file_get_contents($this->filename);echo"从文件读取原始数据\n";return $content ?: ''; }}
装饰类
// 抽象装饰器abstractclassDataSourceDecoratorimplementsDataSource{protected DataSource $wrappee;publicfunction__construct(DataSource $source){$this->wrappee = $source; }publicfunctionwrite(string $data): void{$this->wrappee->write($data); }publicfunctionread(): string{return$this->wrappee->read(); }}
// 加密装饰器classEncryptionDecoratorextendsDataSourceDecorator{private string $key = 'secret-key';publicfunctionwrite(string $data): void{ $encrypted = $this->encrypt($data);echo"加密数据\n";parent::write($encrypted); }publicfunctionread(): string{ $data = parent::read();return$this->decrypt($data); }privatefunctionencrypt(string $data): string{// 简单示例,实际应使用 openssl 等return base64_encode($data); }privatefunctiondecrypt(string $data): string{return base64_decode($data); }}// 压缩装饰器classCompressionDecoratorextendsDataSourceDecorator{publicfunctionwrite(string $data): void{ $compressed = $this->compress($data);echo"压缩数据\n";parent::write($compressed); }publicfunctionread(): string{ $data = parent::read();return$this->decompress($data); }privatefunctioncompress(string $data): string{return gzcompress($data, 9); }privatefunctiondecompress(string $data): string{return gzuncompress($data); }}
调用
// 使用示例$source = new FileDataSource('test.txt');// 只加密$encrypted = new EncryptionDecorator($source);$encrypted->write("Hello World");// 输出: 加密数据 → 写入原始数据到文件echo $encrypted->read();// 输出: 从文件读取原始数据 → Hello World// 同时使用压缩和加密$compressedAndEncrypted = new CompressionDecorator(new EncryptionDecorator($source));$compressedAndEncrypted->write("Sensitive Data");// 输出: 压缩数据 → 加密数据 → 写入原始数据到文件