zlikavac32/nsb-decorators

即时装饰器

0.1.1 2020-12-03 12:28 UTC

This package is auto-updated.

Last update: 2024-09-29 05:28:21 UTC


README

Build Status

即时服务装饰器。

目录

  1. 简介
  2. 安装
  3. 使用
  4. 它是如何工作的?
  5. 限制
  6. 示例

简介

最好从示例开始,让我们这么做。

假设我们有一个命令的接口。它可以运行,就这些。

interface Command
{

    public function run(Input $input, Output $output): int;
}

但是,根据应用程序的实现,命令可以做更多的事情。例如,命令可以有一个与之关联的帮助文本。

interface CommandWithHelp extends Command
{

    public function help(): string;
}

由于我们面向接口,装饰器很常见。可能会提供一个使用装饰的调试输出的装饰器。这样,根据我们如何构建我们的命令,我们会得到不同的行为。

class DebugCommand implements Command
{

    private $command;

    public function __construct(Command $command)
    {
        $this->command = $command;
    }

    public function run(Input $input, Output $output): int
    {
        return $this->command->run($input, new DebugOutput($output));
    }
}

但我们现在有一个问题。因为装饰器不一定实现了具体命令的所有接口,我们可能会丢失一些功能。

class FoOCommand implements CommandWithHelp
{

    public function run(Input $input, Output $output): int
    {
        $output->writeln('Foo');

        return 0;
    }

    public function help(): string
    {
        return 'Command just writes Foo';
    }
}

$command = new DebugCommand(new FooCommand());

$command->help(); // does not work

一个解决方案是将所有额外的接口合并到原始接口中,但这现在强加了大量的方法实现,尽管它们并不需要。我们会回到起点。

另一种方法可能是手动为相同的装饰器定义额外的实现,但这会引入太多新的类。

更好的方法可能是以编程方式实现。这正是这个库所做的。对于给定的装饰器类和主题类(被装饰实例的类),会创建新的代理装饰器类的代码。

安装

推荐通过 Composer 安装。

composer require zlikavac32/nsb-decorators

使用

要为代理装饰器类创建代码,使用 \Zlikavac32\NSBDecorators\Proxy::createClassProxy()。它需要四个参数

  • 代理 FQN - 将生成的类的完全限定名
  • 装饰器 - 装饰器类的 ReflectionClass
  • 主题 - 被装饰的主题类的 ReflectionClass
  • 参数名称 - 接受主题服务的参数名称,不带 $

然后可以将该代码存储在某个地方或评估。

也可以与自动加载器一起使用。使用 \Zlikavac32\NSBDecorators\Proxy::createFQNForProxyClass() 创建代理类名。它接受三个参数,装饰器类、主题类和装饰器类中接受主题的参数名称。类名编码了所有这些参数。

\Zlikavac32\NSBDecorators\Proxy::loadFQN 可以注册为自动加载器以在即时创建代理服务。

它是如何工作的?

收集了两个类中的接口,并计算了差异。代理类将扩展装饰器类,并实现主题实现的接口,而装饰器没有实现的接口。这些方法将只是代理到主题实例。

对于上面的示例,可能会生成类似这样的内容。

namespace Zlikavac32\NSBDecorators\Proxy {

    class Generated_4465627567436f6d6d616e64_466f4f436f6d6d616e64_636f6d6d616e64 extends \DebugCommand implements \CommandWithHelp
    {

        private $command;

        public function __construct(\Command $command)
        {
            parent::__construct($command);

            $this->command = $command;
        }

        public function help(): string
        {
            return $this->command->help();
        }
    }
}

要生成多个装饰器,链中的每个装饰器都必须以相同的方式生成(如果它还没有所需的接口)。

限制

此库旨在用于没有流畅接口的服务装饰器。

不支持静态方法、抽象类和匿名类。出于明显的原因,也不支持最终类。

依赖于未在方法声明中指定的参数的方法被忽略。目前参数是直接映射的。也许将来可能会使用 ...func_get_args()

示例

您可以在示例中看到带有代码注释的更多示例。