【问题标题】:What is the proper way to call methods from a decorator where the method doesn't modify the functionality?从方法不修改功能的装饰器调用方法的正确方法是什么?
【发布时间】:2013-09-26 06:28:25
【问题描述】:

从这个例子中,CoffeeWithCream 的 getBrand() 方法是否不合适或有任何问题?我这样做的原因是避免在任何被调用的地方都写 $coffeeWithCream->$coffee->getBrand()。

特别是,出现的一个关注领域是单元测试。我对单元测试还不够熟悉,不知道这种策略是否会使测试复杂化。

另外,我知道 getBrand() 只是一个简单的访问器方法。如果该方法执行更复杂的任务,答案会改变吗?

Class Coffee {
    public $brand;
    public $ingredients = array('coffee');

    public function getBrand() {
        return $this->brand;
    }

    public function getIngredients() {
        return $this->ingredients;
    }
}

Class CoffeeWithCream {
    public $coffee;

    public __construct(Coffee $coffee) {
        $this->coffee = $coffee;
    }

    public function getIngredients() {
        $ingredients = $this->coffee->getIngredients();
        $ingredients[] = 'cream';
        return $ingredients;
    }

    public function getBrand() {
        $this->coffee->getBrand();
    }
}

【问题讨论】:

  • 我认为单元测试不会那么复杂,因为您能够(并且应该)注入 Coffee 的模拟版本并测试在调用时是否调用了方法 Coffee::getBrand() CoffeeWithCream::getBrand()。反之,当你测试Coffee::getBrand()时,只测试这个特定方法的行为是否正确,反正你会怎么做。

标签: php unit-testing decorator


【解决方案1】:

您应该实现一个抽象装饰器类,它使用与咖啡类相同的接口。这个抽象类主要用于将所有方法调用传递给 Coffee 类。您的具体装饰器从抽象装饰器扩展而来,并且只覆盖他们想要添加功能的特定方法。请参考Wiki 有了这个,您将摆脱 $coffeeWithCream->$coffee->getBrand() 问题。

interface ICoffee 
{
    public function getBrand();

    public function getIngredients();
}


class Coffee implements ICoffee { ... }


abstract class CoffeeDecorator implements ICoffee
{

    protected $coffee;      

    public function __construct(Coffee $coffee)
    {
        $this->coffee = $coffee;
    }

    public function getBrand()
    {
        return $this->coffee->getBrand();
    }

    public function getIngredients()
    {
        return $this->coffee->getIngredients();
    }  

}


class CoffeeWithCream extends CoffeeDecorator
{

    public function getIngredients() 
    {
        $ingredients = parent::getIngredients();
        $ingredients[] = 'cream';
        return $ingredients;
    }

}

【讨论】:

  • 感谢赛斯的澄清。阅读您的参考链接并理解您的答案。 50 名代表的奖励将在 2 小时内发送。再次感谢!
猜你喜欢
  • 2014-10-04
  • 1970-01-01
  • 2021-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-06
  • 1970-01-01
相关资源
最近更新 更多