出于学习目的,我尝试创建一个 GoF Decorator 实现,以将文本转换为压缩文本或加密文本的可能性为例。 <?php interface DataSource { public function gerar($texto): string; public function recuperar($texto) : string; } class TextoBase implements DataSource { public function gerar($texto): string { return $texto; } public function recuperar($texto) : string { return $texto; } } abstract class Decorator implements DataSource { private DataSource $decorado; public function __construct(DataSource $decorado) { $this->decorado = $decorado; } public function gerar($texto): string { return $this->decorado->gerar($texto); } public function recuperar($texto) : string { return $this->decorado->recuperar($texto); } } class CriptoDecorator extends Decorator { const KEY = 'vDIa5JdknBqfrKOu8d7UpddnBMCH1vza'; const NONCE = 'Ra5LeH7ntW2rvkz3dmqI5Stx'; public function gerar($texto): string { return $this->encrypt(parent::gerar($texto)); } public function recuperar($texto): string { return $this->decrypt(parent::recuperar($texto)); } public function encrypt($data) { return sodium_crypto_secretbox($data, self::NONCE, self::KEY); } private function decrypt(string $data): string { return sodium_crypto_secretbox_open($data, self::NONCE, self::KEY); }} class CompressaoDecorator extends Decorator { const NIVEL_COMPRESSAO = 6; public function gerar($texto): string { return $this->comprimir(parent::gerar($texto)); }由于某种原因,我收到警告:Warning: gzuncompress(): data error in C:\wamp64\www\curso\designer_patterns\estrutural\decorator\real_life.php on line 93那么,有没有办法解决这个问题并允许两个装饰器堆叠并用于 gerar(generate) 和 recuperar(retrieve) ?
1 回答
白衣非少年
TA贡献1155条经验 获得超0个赞
您需要按照您设置的顺序展开。如果先压缩然后加密,则需要解密然后解压缩。
此特定代码的快速修复方法是更改您的recuperar方法CompressaoDecorator
class CompressaoDecorator extends Decorator
{
public function recuperar($texto): string
{
return parent::recuperar($this->descomprimir($texto));
}
}
如果你想抽象地解决这个问题,我会用一个可以保证订单的工厂来处理这个问题。为此,我认为单个对象本身不应该关心parent,工厂应该完成链接事物的工作。
编辑
实际上,当我更多地考虑这一点时,您不需要工厂,您只需将所有方法的顺序交换即可recuperar,因此这个也会改变:
class CriptoDecorator extends Decorator
{
public function recuperar($texto): string
{
return parent::recuperar($this->decrypt($texto));
}
}
这应该允许您首先调用加密或压缩,并且只要您使用相同的链,相反的操作也应该起作用。
- 1 回答
- 0 关注
- 116 浏览
添加回答
举报
0/150
提交
取消