试图在php中实现(理解)Decorator模式

时间:2011-06-15 15:55:45

标签: php design-patterns

我正在尝试理解Decorator模式,并且我已经阅读了有关SO的其他相关问题,然后我决定尝试一个简单的例子(我是一个PHP新手):

interface iTitle {
   public function getTitle();
}

class Title implements iTitle {
   protected $_text;

   public function __construct() {
      $this->_text='Our page';
   }

   public function getTitle() {
      return $this->_text;
   }
}

abstract class TitleDecorator implements iTitle {
   protected $_title;

   public function __construct(iTitle $title) {
      $this->_title=$title;
   }
}

class BeforeTitle extends TitleDecorator {
   public function getTitle() {
      return 'Welcome to '.$this->_title->getTitle();
   }
}

class AfterTitle extends TitleDecorator {
   public function getTitle() {
      return $this->_title->getTitle().', Dear user!';
   }
}

这是Decorator模式的(某种)正确实现吗? 如果不是,那么正确的方法是什么? 如果是的话,这可以改进吗? 或者这可能更适合另一种模式?

任何帮助/想法将不胜感激,提前谢谢!

2 个答案:

答案 0 :(得分:6)

  

这是Decorator模式的(某种)正确实现吗?

  

如果是,可以改进吗?或者这可能更适合另一种模式?

你实现了装饰模式。当你想要实现一个模式时,我无法想象什么是比装饰模式更好的模式。

通常,人们会使用Decorator来实现一个接口,并且只替换原始对象的一小部分并传递其余部分。这严重依赖于对象的使用。由于您的代码仅显示如何实现模式而不是对象的使用,因此无论该模式是否符合您的需求,都无法具体回答。

所以你也可以实现其他模式,然后决定哪一种感觉更好。模式的关键在于:只有当你知道存在哪种模式时,你才能使用它们。

因此,模式和决定选择哪一个通常是OOAD。如果您是新手,checkout this nice book

关于您的代码

当你问起这是否正确时,我首先回答是。它是正确的,但这部分看起来对我来说是第二次看错了:

class BeforeTitle extends TitleDecorator {
   public function getTitle() {
      return 'Welcome to '.$this->getTitle();
   }
}

这是错误的,因为类BeforeTitle中的getter以递归方式调用自身(它一次又一次地调用自身......)。我认为这不是你想要的。

你在另一个装饰器类中执行它是正确的,引用$this->_title这是被装饰的对象实例:

class AfterTitle extends TitleDecorator {
   public function getTitle() {
      return $this->_title->getTitle().', Dear user!';
   }
}

如果要替换/扩展对象行为,但是您希望在不需要完全重写对象功能的情况下执行此操作,则可以使用Decorator模式。但其他人可以比我更好地描述。

答案 1 :(得分:0)

在装饰器模式中,您应始终注入值而不是在构造函数内初始化。示例: 这是错误的方式。

class Title implements iTitle {
   protected $_text;

   public function __construct() {
      $this->_text='Our page';
   }

   public function getTitle() {
      return $this->_text;
   }
}

这是正确的方法:

 class Title implements iTitle {
   protected $_text;

   public function __construct($text) {
      $this->_text=$text;
   }

   public function getTitle() {
      return $this->_text;
   }
}

如果您需要更详细的真实示例,请参阅链接here