在做一些关于Decorator模式的教程时,我遇到了两种不同的实现。
实现1(简称I1)
实现2(简称I2)
总之,
I1的父装饰器类实现了原对象的接口(在本例中,PropertyDecorator
类实现了PropertyInterface
)。原对象Property
也实现了PropertyInterface
)。
I2的父装饰器类没有实现原始对象的接口(在这个例子中,Decorator_Wrapper
没有实现Cupcake
接口)。事实上,根本就没有CupcakeInterface
)。
这仅仅是理解和实现Decorator模式的个人偏好吗?或者一个是错的,一个是对的?
这取决于你的需要。让我们看看:
抽象类
- 可以提供抽象方法。
- 可以提供真实的函数和变量
- 可以扩展。但是一个类只能继承一个父类。
界面
- 可以提供抽象方法。
- 一个类可以实现多个接口
我通常更喜欢使用基抽象类,因为我也可以声明一些基本函数,因为你可以有很多不同类型的装饰器具有类似的功能。方法无论如何都可以被重写+你可以实现一些接口。
class Decorator extends Decorator_Wrapper implements Interface1, Inteface2 {
public function __construct(){
parent::__construct() ; // Here you could perform some basic decorator actions. It is an advantage compared to interfaces.
}
}
当您希望在不扩展类本身的情况下扩展类实例的功能(因此,不影响该类的其他实例)时,可以使用Decorator模式。
它是一种运行时的扩展,它非常有用,因为它允许你在运行时自定义对象的行为。你甚至可以用它"模拟"多重继承。
因为你的两个例子都做到了这一点,所以都是正确的。不需要装饰器来实现基本接口或扩展原始对象。
然而…
如果装饰器没有实现基接口,它可能无法与原始类互换使用。
如果你不能在任何地方"安全地"使用装饰器,这可能会破坏使用它的目的。
的例子:
interface FooInterface {
public function scare();
}
class Foo implements FooInterface {
protected $boo = 'boo';
public function scare() { echo $this->boo; }
}
class FooBar {
public function __construct(FooInterface $foo) {
$this->foo = $foo;
}
public function scareAlot() {
echo strtoupper($this->foo->scare());
}
}
class INeedFoo {
public static function gimmeFoo(FooInterface $foo) {}
}
$foo = new Foo();
$fooBar = new FooBar($foo);
INeedFoo::gimmeFoo($foo); //Works
INeedFoo::gimmeFoo($fooBar); //Does not Work
此外,如果你实现基接口或扩展基类,可能更容易在彼此之上添加多个装饰器,但是……您还可能最终得到大量复制的功能。