【问题标题】:Two different ways to implement Decorator pattern in PHP在 PHP 中实现装饰器模式的两种不同方法
【发布时间】:2013-05-04 10:34:32
【问题描述】:

在做一些关于装饰器模式的教程时,我遇到了两种不同的实现。

Implementation 1(简称I1)

Implementation 2(简称I2)

总之,

I1 的父装饰器类实现了原始对象的接口(在示例中,类PropertyDecorator 实现了PropertyInterface。原始对象Property 也实现了PropertyInterface

I2 的父装饰器类没有实现原始对象的接口(在示例中,Decorator_Wrapper 没有实现Cupcake 接口。实际上,甚至根本没有CupcakeInterface)。

我的问题是,

这仅仅是理解和实现装饰器模式的个人偏好吗?还是一错一对?

【问题讨论】:

    标签: php design-patterns decorator


    【解决方案1】:

    这取决于您的需求。 让我们看看:

    抽象类

    • 可以提供抽象方法。
    • 可以提供真实的函数和变量。
    • 可以扩展。但是一个类只能扩展一个父类。

    界面

    • 可以提供抽象方法。
    • 一个类可以实现多个接口。

    我通常更喜欢使用基本抽象类,因为我也可以声明一些基本函数,因为您可以拥有许多具有相似功能的不同类型的装饰器。无论如何都可以覆盖方法+您可以实现一些接口。

    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.
      }
    }
    

    【讨论】:

    【解决方案2】:

    当您希望扩展类实例的功能而不扩展类本身时使用装饰器模式(因此,不会影响该类的其他实例)。

    它是运行时的一种扩展,非常有用,因为它允许您在运行时自定义对象的行为。你甚至可以用它“模拟”多重继承。

    由于您的两个示例都实现了这一点,因此两者都是正确的。不需要装饰器来实现基接口或扩展原始对象。


    但是...


    如果装饰器没有实现基接口,它可能无法与原始类互换使用。

    如果您不能“安全”地在任何地方使用装饰器,这可能会破坏使用装饰器的目的。

    例子:

    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
    

    此外,如果您实现基接口或扩展基类,则可能更容易在彼此之上添加多个装饰器,但是...您最终可能会得到很多复制的功能。

    【讨论】:

    • 您的意思是写class Foo implements FooInterface 而不是class FooINeedFoo::gimmeFoo($foo) 在我运行此代码时也会返回错误。
    猜你喜欢
    • 2016-04-29
    • 1970-01-01
    • 2013-07-03
    • 2014-12-29
    • 2012-02-16
    • 2011-03-08
    • 2019-03-25
    • 2011-09-15
    • 2013-02-25
    相关资源
    最近更新 更多