PHP設(shè)計(jì)模式漫談之調(diào)解者模式
原創(chuàng)【51CTO獨(dú)家特稿】本周的《PHP設(shè)計(jì)模式漫談》系列,我們將給大家介紹調(diào)解者模式,這個(gè)模式的目的是封裝一組對(duì)象之間的相互作用,防止對(duì)象之間相互干擾,調(diào)解者(Mediator)在同事對(duì)象(Colleague)之間充當(dāng)中間匯聚點(diǎn)。
同事對(duì)象之間應(yīng)該保持松散耦合,避免一個(gè)對(duì)象直接明確指向另一個(gè)對(duì)象。在調(diào)解者模式下,對(duì)象的關(guān)系和依賴發(fā)生沖突時(shí),我們可以使用調(diào)解者在耦合的對(duì)象之間協(xié)調(diào)工作流,依賴可以從同事朝調(diào)解者或從調(diào)解者向同事建立,這兩個(gè)方向上的依賴都可以使用AbstractColleague或AbstractMediator中斷。
圖1 調(diào)解者和同事對(duì)象
對(duì)象不是孤立的,對(duì)象之間必須相互協(xié)作才能完成任務(wù)。雖然調(diào)解者模式可以限制對(duì)象之間的相互作用,但如果濫用,會(huì)致使編寫聚合性類變得非常困難。舉一個(gè)實(shí)用的例子,在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain-Driven Design)中的服務(wù)就是實(shí)體之間的調(diào)解者。再舉一個(gè)PHP相關(guān)的例子,Zend_Form裝飾和過濾功能實(shí)際上可以看作是Zend_Form_Decorator和Zend_Filter實(shí)例之間的一個(gè)簡(jiǎn)單調(diào)解者,它們都使用Zend_Validate對(duì)象進(jìn)行驗(yàn)證。
當(dāng)調(diào)解者必須監(jiān)聽同事對(duì)象的事件時(shí),它通常是作為觀察者(Observer)實(shí)現(xiàn)的,產(chǎn)生一個(gè)黑板(blackboard)對(duì)象,一些同事寫,另一些同事就讀。來自同事的事件被推向調(diào)解者,再由調(diào)解者將其轉(zhuǎn)發(fā)給其它訂閱的同事,同事之間不需要相互了解,這個(gè)架構(gòu)成功用于隨Zend框架發(fā)布的Dojo JavaScript庫。這個(gè)模式的另一個(gè)好處是對(duì)象的變化包含在計(jì)算方法中,可以通過配置不同的調(diào)解者實(shí)現(xiàn)這一目標(biāo),但實(shí)例化相關(guān)對(duì)象將是一個(gè)松散的操作,不同容器和工廠之間的協(xié)作關(guān)系將是分散的。參與者:
◆同事(Colleague):重點(diǎn)是它的職責(zé),它只與一個(gè)調(diào)解者M(jìn)ediator或AbstractMediator通信。
◆調(diào)解者(Mediator):協(xié)同多個(gè)Colleagues(AbstractColleagues)共同工作。
◆AbstractMediator,AbstractColleague:從這些角色的真實(shí)實(shí)現(xiàn)解耦的可選接口,可能不止一個(gè)AbstractColleague角色。
下面的代碼實(shí)現(xiàn)了一個(gè)表單輸入的過濾過程,類似于Zend_Form_Element功能。
- <?php
- /**
- * AbstractColleague.
- */
- interface Filter
- {
- public function filter($value);
- }
- /**
- * Colleague. We decide in the implementation phase
- * that Colleagues should not know the next Colleague
- * in the chain, resorting to a Mediator to link them together.
- * This choice succesfully avoids a base abstract class
- * for Filters.
- * Remember that this is an example: it is not only
- * Chain of Responsibility that can be alternatively implemented
- * as a Mediator.
- */
- class TrimFilter implements Filter
- {
- public function filter($value)
- {
- return trim($value);
- }
- }
- /**
- * Colleague.
- */
- class NullFilter implements Filter
- {
- public function filter($value)
- {
- return $value ? $value : '';
- }
- }
- /**
- * Colleague.
- */
- class HtmlEntitiesFilter implements Filter
- {
- public function filter($value)
- {
- return htmlentities($value);
- }
- }
- /**
- * The Mediator. We avoid referencing it from ConcreteColleagues
- * and so the need for an interface. We leave the implementation
- * of a bidirectional channel for the Observer pattern's example.
- * This class responsibility is to store the value and coordinate
- * filters computation when they have to be applied to the value.
- * Filtering responsibilities are obviously a concern of
- * the Colleagues, which are Filter implementations.
- */
- class InputElement
- {
- protected $_filters;
- protected $_value;
- public function addFilter(Filter $filter)
- {
- $this->_filters[] = $filter;
- return $this;
- }
- public function setValue($value)
- {
- $this->_value = $this->_filter($value);
- }
- protected function _filter($value)
- {
- foreach ($this->_filters as $filter) {
- $value = $filter->filter($value);
- }
- return $value;
- }
- public function getValue()
- {
- return $this->_value;
- }
- }
- $input = new InputElement();
- $input->addFilter(new NullFilter())
- ->addFilter(new TrimFilter())
- ->addFilter(new HtmlEntitiesFilter());
- $input->setValue(' You should use the <h1>-<h6> tags for your headings.');
- echo $input->getValue(), "\n";
原文名:Practical Php Patterns: Mediator 作者:Giorgio
原文出處:http://giorgiosironi.blogspot.com/search/label/practical%20php%20patterns
【PHP設(shè)計(jì)模式漫談】