PHP装饰器模式解密后如何使用解压?

PHP How to use decompression after decryption using Decorator Pattern?

出于学习目的,我尝试创建一个 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));
        }
        public function recuperar($texto): string {
            return $this->descomprimir(parent::recuperar($texto));
        }
        private function comprimir(string $stringData): string {
            return gzcompress($stringData, self::NIVEL_COMPRESSAO);
        }
        private function descomprimir(string $stringData): string {
            return gzuncompress($stringData);
        }
    }
    $texto = "olá mundo !";
    $decorado = new CompressaoDecorator(new CriptoDecorator(new TextoBase()));
    $texto_decorado = $decorado->gerar($texto);
    echo PHP_EOL;
    echo $decorado->recuperar($texto_decorado);

出于某种原因,我收到了警告:

Warning: gzuncompress(): data error in C:\wamp64\www\curso\designer_patterns\estrutural\decorator\real_life.php on line 93

那么,有没有办法解决这个问题并允许堆叠两个装饰器并用于 gerar(generate) 和 recuperar(retrieve)?

提前致谢

您需要按照您设置的相同顺序放松。如果先压缩再加密,则需要先解密再解压

此特定代码的快速修复是更改 CompressaoDecorator

中的 recuperar 方法
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));
    }
}

这应该允许您先调用加密或压缩,只要您使用相同的链,反向也应该有效。