策略模式上下文中的多种策略

时间:2018-08-02 17:19:28

标签: php oop strategy-pattern

我对策略模式有疑问。通常,策略模式如下:

class TaxCalculatorContext
{
    private $strategy;

    public function setStrategy(TaxCalculatorStrategyInterface $strategy)
    {
        $this->strategy = $strategy;
    }

    public function execute($amount)
    {
        return $this->strategy->calculate($amount);
    }
}

class TaxCalculatorOntario implements TaxCalulatorStrategyInterface
{
    public function calculate($amount)
    {
        ...calculate ontario taxes here
    }
}

class TaxCalculatorQuebec implements TaxCalculatorStrategyInterface
{
    public function calculate($amount)
    {
        ...calculate quebec taxes here
    }
}

interface TaxCalculatorStrategyInterface
{
    public function calculate($amount);
}

我想知道在上下文中使用多种策略是否可以接受。请查看下面的代码。

class TaxCalculatorContext
{
    private $strategies;

    public function addStrategy(TaxCalculatorStrategyInterface $strategy)
    {
        $this->strategies[] = $strategy;
    }

    public function execute($amount)
    {
        foreach ($this->strategies as $strategy)
        {
            if($strategy->canCalculate)
            {
                return $strategy->calculate($amount);
            }
        }
    }
}

class TaxCalculatorOntario implements TaxCalulatorStrategyInterface
{
    public function canCalculate($amount)
    {
        ... returns true or false
    }

    public function calculate($amount)
    {
        ...calculate ontario taxes here
    }
}

class TaxCalculatorQuebec implements TaxCalculatorStrategyInterface
{
    public function canCalculate($amount)
    {
        ... returns true or false
    }

    public function calculate($amount)
    {
        ...calculate quebec taxes here
    }
}

interface TaxCalculatorStrategyInterface
{
    public function canCalculate($amount);
    public function calculate($amount);
}

如您所见,我不仅在传递一种策略,还在TaxCalculatorContext中创建了一系列策略。然后,当调用execute方法时,将循环执行策略,并且将执行canCalulate方法中返回true的第一个策略。那么这是标准做法还是我应该避免?

1 个答案:

答案 0 :(得分:2)

如果它适合您的问题,那么我看不出您不喜欢的任何原因。如果要将其改造为现有的策略结构,则可以使用Composite模式进行调查。您使用它的方式是创建一个新的策略子类,该子类接受其构造函数或工厂的多个 other 策略。然后,在策略本身内部,它将在必要时执行子策略。这样,您无需更改策略界面,并且调用该策略的客户端代码也无需知道甚至有多个策略。

但是,如果您不进行改进,并且在问题领域中包含多种策略的想法,那么可以说可以避免实现Composite所增加的复杂性,并按照说明进行操作。在物体上抛出越来越多的图案并不总是必要的,或者就速度而言并不是有效的。只要您想将多种策略的思想与客户端代码脱钩,就可以将Composite用作将来的重构选项。

关于您给出的示例的两个说明(您可能已经知道,但以防万一):首先,如当前所写,多重策略示例将执行每个策略,其谓词返回true,而不仅仅是谓词第一个(如果希望该行为,则在计算第一个后需要一个break语句)。其次,您在应用程序中散布的状态越多,潜在的错误就越多。因此,可能需要考虑从Strategy :: calculate()返回返回的计算值,而不是像接口当前所暗示的那样将其存储在策略中。这将使您的策略成为无状态函子,这是可取的,因为这样您就不必考虑管理其状态了。

相关问题