3

From this example, is CoffeeWithCream's getBrand() method improper or problematic in any way? My reason for doing it this way is to avoid writing $coffeeWithCream->$coffee->getBrand() everywhere it's called.

Particularly, one area of concern that's surfaced is unit testing. I'm not comfortable enough yet with Unit Testing to know whether this strategy complicates testing.

Also, I know that getBrand() is just a simple accessor method. What if the method performed a more complex task, would the answer change?

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

1 回答 1

3

您应该实现一个抽象装饰器类,它使用与咖啡类相同的接口。这个抽象类主要用于将所有方法调用传递给 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;
    }

}
于 2013-09-24T20:53:29.017 回答