这本书说:
The decorator pattern can be used to extend (decorate) the
functionality of a certain object
我有一只兔子动物.我希望我的兔子能够拥有爬行动物的皮肤.只是想用爬行动物的皮肤装饰一只普通的兔子.
我有代码.首先,我有一个抽象类动物,每个动物都是常见的动物:
abstract class Animal {
abstract public function setSleep($hours);
abstract public function setEat($food);
abstract public function getSkinType();
/* and more methods which for sure will be implemented in any concrete animal */
}
我为我的兔子创建课程:
class Rabbit extends Animal {
private $rest;
private $stomach;
private $skinType = "hair";
public function setSleep($hours) {
$this->rest = $hours;
}
public function setFood($food) {
$this->stomach = $food;
}
public function getSkinType() {
return $this->$skinType;
}
}
到目前为止一切正常.然后我创建了扩展Animal的抽象AnimalDecorator类:
abstract class AnimalDecorator extends Animal {
protected $animal;
public function __construct(Animal $animal) {
$this->animal = $animal;
}
}
而这里的问题来了.注意AnimalDecorator也从Animal类中获取所有抽象方法(在这个例子中只有两个但实际上可以有更多).
然后我创建了扩展AnimalDecorator的具体ReptileSkinDecorator类.它还有与Animal相同的两种抽象方法:
class ReptileSkinDecorator extends AnimalDecorator {
public function getSkinColor() {
$skin = $this->animal->getSkinType();
$skin = "reptile";
return $skin;
}
}
最后我想用爬行动物的皮肤装饰我的兔子:
$reptileSkinRabbit = ReptileSkinDecorator(new Rabbit());
但是我不能这样做,因为我在ReptileSkinDecorator类中有两个抽象方法.他们是:
abstract public function setSleep($hours);
abstract public function setEat($food);
所以,不仅仅重新装饰皮肤,我还必须重新装饰setSleep()和setEat();方法.但我不需要.
在所有书籍示例中,Animal类中始终只有一个抽象方法.当然,它的工作原理.但是在这里我只是制作了一个非常简单的现实生活示例,并尝试使用Decorator模式,如果没有在ReptileSkinDecorator类中实现这些抽象方法,它就无法工作.
这意味着如果我想使用我的例子,我必须创建一个全新的兔子,并为它实现自己的setSleep()和setEat()方法.好的,就这样吧.但后来这个全新的兔子有了commont Rabbit的例子我传给了ReptileSkinDecorator:
$reptileSkinRabbit = ReptileSkinDecorator(new Rabbit());
我在reptileSkinRabbit实例中有一个常见的兔子实例,它有自己的方法,后者又有自己的reptileSkinRabbit方法.我有兔子兔子.但我认为我没有这种可能性.
我不理解Decarator模式的正确方法.在我对这种模式的理解中,请你指出我的例子中的任何错误.
谢谢.
解决方法:
听起来你正试图强迫使用不适合问题的特定模式.装饰者通常聚集一些额外的东西(向头发添加辫子),而不是完全改变它,就像你试图用皮肤(头发到鳞片).
A Builder pattern(您指定构建对象的方式)可以更好地适应问题.在你的情况下,你想要建立一个用爬行动物皮肤建造的兔子. (我来自哪里,而不是爬行动物的皮肤,制作一只有角的兔子并将其称为jackalope :)会很有趣:)
我认为在这里使用Builder(或任何模式)可能实际上是矫枉过正.你是否必须使用这种特殊问题的模式?如何定义代码如下并暂时保留模式:
class Animal {
private $rest;
private $stomach;
private $skinType;
public function setSleep($hours) {
$this->rest = $hours;
}
public function setFood($food) {
$this->stomach = $food;
}
public function setSkinType($skin) {
$this->skinType = $skin;
}
// define the other getters too
public function getSkinType() {
return $this->$skinType;
}
}
class Rabbit extends Animal {
public function __construct() {
$this->rest = "rabbitRest"; // put whatever a rabbit rest is
$this->stomach = "rabbitStomach"; // put whatever a rabbit stomach is
$this->skinType = "hair";
}
}
免责声明:我是一个人,我的PHP非常糟糕,我确定这个代码有几个问题,但我希望你能得到这个想法.
所以兔子只会扩展一个Animal并相应地设置它的属性.然后,如果有人想要一个RabbitReptile,他们可以扩展兔子(可能是矫枉过正)或者只是制作一只兔子并相应地设置皮肤类型.