当您希望扩展类实例的功能而不扩展类本身(因此,不影响所述类的其他实例)时,使用装饰器模式。
它是运行时的一种扩展,非常有用,因为它允许您在运行时自定义对象的行为。你甚至可以用它“模拟”多重继承。
由于您的两个示例都实现了这一点,因此两者都是正确的。不需要装饰器来实现基本接口或扩展原始对象。
然而...
如果装饰器没有实现基接口,它可能无法与原始类互换使用。
如果您不能“安全地”在任何地方使用它,这可能会破坏使用装饰器的目的。
例子:
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
此外,如果您实现基接口或扩展基类,则可能更容易在彼此之上添加多个装饰器,但是......您最终也可能会得到很多复制的功能。