繁体   English   中英

PHP 嵌套函数 OOP

[英]PHP Nesting functions OOP

我正在使用一个库,它具有以下过程来将许多操作附加到一个事件

$action = (new EventBuilder($target))->addOperation($Operation1)->addOperation($Operation2)->addOperation($Operation3)->compile();

我不确定如何根据我需要做的事情动态添加操作。

像这样的东西

$action = (new EventBuilder($target));

while (some event)
{
$action = $action->addOperation($OperationX);
}

$action->compile();

我需要能够在 while 循环中动态添加操作,并在所有操作都添加后运行它。

先感谢您

您提出的解决方案将起作用。 EventBuilder 提供了所谓的Fluent Interface ,这意味着有一些方法可以返回构建器本身的实例,允许您根据需要多次调用addOperation ,然后调用compile方法来产生结果。 但是,您可以随意忽略addOperation的返回值,只要您有一个包含最终可以调用compile的构建器实例的变量。

和我一起散步...

// Some boilerplate classes to work with
class Target
{
    private ?string $name;
    
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    
    public function getName(): string
    {
        return $this->name;
    }
}

class Operation
{
    private ?string $verb;
    
    public function __construct(string $verb)
    {
        $this->verb = $verb;
    }
    
    public function getVerb(): string
    {
        return $this->verb;
    }
}

class Action
{
    private ?Target $target;
    private array   $operations = [];
    
    public function __construct(Target $target, array $operations)
    {
        $this->target     = $target;
        $this->operations = $operations;
    }
    
    /**
     * Do the things
     * @return array
     */
    public function run(): array
    {
        $output = [];
        foreach ($this->operations as $currOperation)
        {
            $output[] =  $currOperation->getVerb() . ' the ' . $this->target->getName();
        }
        
        return $output;
    }
}

以下是您的 EventBuilder 在幕后所做的基本解释:


class EventBuilder
{
    private ?Target $target;
    private array   $operations = [];
    
    public function __construct(Target $target)
    {
        $this->target = $target;
    }
    
    /**
     * @param Operation $operation
     * @return $this
     */
    public function addOperation(Operation $operation): EventBuilder
    {
        $this->operations[] = $operation;
        
        // Fluent interface - return a reference to the instance
        return $this;
    }
    
    public function compile(): Action
    {
        return new Action($this->target, $this->operations);
    }
}

让我们尝试这两种技术并证明它们会产生相同的结果:

// Mock some operations
$myOperations = [
    new Operation('Repair'),
    new Operation('Clean'),
    new Operation('Drive')
];

// Create a target
$target = new Target('Car');

/*
 * Since the EventBuilder implements a fluent interface (returns an instance of itself from addOperation),
 * we can chain the method calls together and just put a call to compile() at the end, which will return
 * an Action instance
 */
$fluentAction = (new EventBuilder($target))
                    ->addOperation($myOperations[0])
                    ->addOperation($myOperations[1])
                    ->addOperation($myOperations[2])
                    ->compile();

// Run the action
$fluentResult = $fluentAction->run();

// Traditional approach, create an instance and call the addOperation method as needed
$builder = new EventBuilder($target);

// Pass our mocked operations
while (($currAction = array_shift($myOperations)))
{
    /*
     * We can ignore the result from addOperation here, just keep calling the method
     * on the builder variable
     */
    $builder->addOperation($currAction);
}

/*
 * After we've added all of our operations, we can call compile on the builder instance to
 * generate our Action.
 */
$traditionalAction = $builder->compile();

// Run the action
$traditionalResult = $traditionalAction->run();

// Verify that the results from both techniques are identical
assert($fluentResult == $traditionalResult, 'Results from both techniques should be identical');

// Enjoy the fruits of our labor
echo json_encode($traditionalResult, JSON_PRETTY_PRINT).PHP_EOL;

Output:

[
    "Repair the Car",
    "Clean the Car",
    "Drive the Car"
]

Rob Ruchte 感谢您的详细解释,我没有包括的一件事是每个操作本身都有 ->build() 调用,我需要将其移至每个 $builder 以使其工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM