从这个例子来看,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 类。您的混凝土装饰器从抽象装饰器扩展而来,并且仅覆盖它们要向其添加功能的特定方法。请参考维基有了这个,你将摆脱你的$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;
}
}