【问题标题】:Strategy Pattern with Anonymous Function Closure具有匿名函数闭包的策略模式
【发布时间】:2019-01-15 00:39:05
【问题描述】:

我想在 php 中使用闭包来实现 Stategy 模式。使用闭包的主要优点是通过创建额外的类来减少样板和代码的数量。通常模式如下所示:

interface StateDiscountCalculatorInterface
{
    public function calculateDiscount($amount);
}


class NewYorkStateStrategy implement StateDiscountCalculatorInterface
{
    public function calculateDiscount($amount)
    {
        // .... about 20 lines of code
    }
}

class CaliforniaStateStrategy implement StateTaxCalculatorInterface
{
    public function calculateDiscount($amount)
    {
       // .... about 20 lines of code that's different from New York State Strategy
    }
}

class stateTaxContext
{
    private $stategy;

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

    public function getDiscount(array $amount)
    {
        return $this->strategy->calculateDiscount($amount);
    }

}

下面的版本是带有实现 php 功能接口的闭包。这是正确的做法吗?

interface StateDiscountCalculatorInterface
{
    public function calculateDiscount($amount);
}


class stateTaxContext
{
    private $newYorkStateStrategy;
    private $californiaStateStrategy;
    private $state;

    public function __construct()
    {
        $this->newYorkStateStrategy = function () implements StateDiscountCalculatorInterface {
            ...NewYorkStateStrategy class is replaced with code here
        };

        $this->californiaStateStrategy = function () implements StateDiscountCalculatorInterface {
            ...CaliforniaStateStrategy class is replaced with code here
        };
    }

    public function getDiscount(array $amount)
    {
        if($this->state==='california')
        {
            $this->californiaStateStrategy->calculateDiscount($amount);
        }
    }

}

【问题讨论】:

  • 我觉得这是解决问题的不好方法。我不知道除了税收的基本乘数之外是否还有其他东西,但我会创建一个包含州名和税收乘数的数组。例如 array( 'Michigan' => 0.06, 'Nevada' => 0.0685, ...) 然后只需创建一个函数以使用状态作为键获取值并将其乘以价格
  • 否则你要创建 50 多个类或闭包,这似乎不是最好的主意
  • 这是对模式的过度简化,假设每个类有 20 行操作要做。我不确定您是否了解您的回答所判断的策略模式。
  • 我也想知道,我会等待比我更了解闭包的人来解决这个问题。我仍然觉得这是使用闭包的错误原因。我认为 $california = function($price) { return $price *0.0725 } 使用了闭包,然后您将其称为 if($state == 'California') { $tax = $california($price);}
  • 我知道你想实现策略模式,但我不确定这是不是最好的情况。也许看看模板方法

标签: php functional-programming closures anonymous-function strategy-pattern


【解决方案1】:

我不是设计模式专家,但在我看来,实现策略模式的最佳方法之一如下 - 您可以保持接口和策略类不变,但实现如下上下文:

class StateTaxContext
{
    private $state;

    public function setState(StateDiscountCalculatorInterface $state)
    {
        $this->state = $state;
    }

    public function getDiscount(array $amount)
    {
        return $this->state->->calculateDiscount($amount);
    }
}

然后你可以在你的代码中到处使用这个模式,像这样:

$context = new StateTaxContext();

// Calculate NY discount?
$context->setState(new NewYorkStateStrategy());
$data = $context->getDiscount($amount);

// Calculate California discount?
$context->setState(new CaliforniaStateStrategy());
$data = $context->getDiscount($amount);

【讨论】:

  • 这正是我通常实现此模式的方式,但我想使用原始问题中所写的闭包来实现。
  • 嗯,我明白了,我想它会起作用,但我认为这不是实现这种模式的最佳方式,至少因为它违反了 SOLID 原则——好的做法是您希望将每个策略的实现逻辑保留在其单独的类中(单一职责)。
  • 函数能实现接口吗?我怀疑是这样。但是,您可以尝试使用匿名类,例如:class implements Interface { { function... } }.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多