Php 匿名函数闭包策略模式

Php 匿名函数闭包策略模式,php,functional-programming,closures,anonymous-function,strategy-pattern,Php,Functional Programming,Closures,Anonymous Function,Strategy Pattern,我想在php中使用闭包实现策略模式。使用闭包的主要优点是通过创建额外的类来减少所需的样板文件和代码量。通常模式如下所示: interface StateDiscountCalculatorInterface { public function calculateDiscount($amount); } class NewYorkStateStrategy implement StateDiscountCalculatorInterface { public function

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

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);
    }

}
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);
下面的版本是一个闭包,实现了一个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);
        }
    }

}

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

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);
    }

}
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);
然后,您可以在代码中的任何地方使用此模式,如下所示:

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);
    }

}
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);

我觉得这是一种处理问题的糟糕方式。我不知道除了基本的税收乘数还有什么,但我会创建一个包含州名称和税收乘数的数组。例如,数组('Michigan'=>0.06,'Nevada'=>0.0685,…),然后创建一个函数,使用状态作为键获取值,并将其乘以价格,否则您将创建50多个类或闭包,这似乎不是最好的想法。这是对模式的过度简化,假设每个类有20行操作要做。我不确定你是否知道根据你的答案判断的战略模式是什么。我也想知道,我会等待比我更了解闭包的人来解决这个问题。我仍然觉得这是使用闭包的错误原因。我认为$california=function($price){return$price*0.0725}使用闭包,然后您可以这样称呼它($state=='california'){$tax=$california($price);}我知道您想要实现策略模式,但我不确定这是最好的情况。也许看看模板方法,这正是我通常实现这个模式的方式,但我想用原始问题中所写的闭包来实现。好吧,我明白了,我想它会起作用,但我认为这不是实现这个模式的最佳方式,至少因为它打破了坚实的原则——良好的实践是,您希望将每个策略的实现逻辑保留在单独的类中(单个职责)。函数能够实现接口吗?我对此表示怀疑。但是,您可以尝试使用匿名类,例如:
类实现接口{{function…}