我刚刚开始学习设计模式,我有两个关于装饰器的问题……
我想知道为什么装饰器模式建议装饰器实现它所装饰的组件的所有公共方法?
难道不能只使用装饰器类来提供额外的行为,然后使用具体的组件(传入其中)来调用其他所有内容吗?
其次,如果您要装饰的具体组件没有抽象装饰器也可以从中派生的基类,该怎么办?
提前感谢!
发布于 2009-02-03 00:55:45
我想你误解了Decorator的意思。您正在考虑使用附加功能扩展一个具体类的简单情况。在这种情况下,是的,在大多数面向对象语言中,派生类可以简单地允许其超类处理任何未实现的方法。
class Base {
function foo() {
return "foo";
}
function bar() {
return "bar";
}
}
// Not what we think of as a Decorator,
// really just a subclass.
class Decorator extends Base {
// foo() inherits behavior from parent Base class
function bar() {
return parent::bar() . "!"; // add something
}
}Decorator类不会扩展它的“装饰”类的基类。它是一个不同的类型,它有一个修饰类的成员对象。因此,如果只是为了调用修饰对象的相应方法,它必须实现相同的接口。
class Decorator { // extends nothing
protected $base;
function __construct(Base $base) {
$this->base = $base;
}
function foo() {
return $base->foo();
}
function bar() {
return $base->foo() . "!"; // add something
}
}为装饰类和装饰器类都定义一个接口(如果您的语言支持这样的东西)可能是值得的。这样,您就可以在编译时检查Decorator是否实现了相同的接口。
interface IBase {
function foo();
function bar();
}
class Base implements IBase {
. . .
}
class Decorator implements IBase {
. . .
}Re:@Yossi Dahan的评论:我在维基百科的文章中看到了模棱两可的地方,但如果你仔细阅读,它确实说被修饰的组件是装饰器对象中的一个字段,并且该组件被作为参数传递给装饰器构造函数。这不同于继承。
尽管wikipedia的文章确实提到了装饰器继承自组件,但您应该将其视为实现接口,如我在上面的PHP示例中所示。装饰器仍然必须代理component对象,如果它继承了组件对象,它就不会代理。这允许装饰器修饰实现该接口的任何类的对象。
以下是Gamma、Helm、Johnson和Vlisside的“设计模式:可重用面向对象软件的元素”中的一些摘录:
装饰器
意图
动态地将附加职责附加到对象。装饰器为扩展功能的子类化提供了灵活的替代方案。
动机
..。装饰器符合它所装饰的组件的接口,因此它的存在对组件的客户端是透明的。
参与者
发布于 2009-02-03 01:04:52
我想知道为什么装饰器模式建议装饰器实现它所装饰的组件的所有公共方法?
装饰器应该是它所装饰的组件的替代品,具有额外的功能(“装饰”)。只有当它完全实现组件的接口时,才会发生这种情况。
装饰器类不能只用来提供额外的行为,然后用具体的组件(传递给它)来调用所有其他的东西吗?
这对装饰器是如何实现的做出了假设。您不能确保它所修饰的组件的整个公共接口都是直接传递的。装饰器有可能在其实现中覆盖某些方法。
;其次,如果您要装饰的具体组件没有抽象装饰器也可以从中派生的基类,该怎么办?
装饰器通常继承它们正在装饰的组件的类,而不是组件的基类。
https://stackoverflow.com/questions/505641
复制相似问题