PHP设计模式之调解者模式的深入解析
调解者模式,这个模式的目的是封装一组对象之间的相互作用,防止对象之间相互干扰,调解者(mediator)在同事对象(colleague)之间充当中间汇聚点。同事对象之间应该保持松散耦合,避免一个对象直接明确指向另一个对象。在调解者模式下,对象的关系和依赖发生冲突时,我们可以使用调解者在耦合的对象之间协调工作流,依赖可以从同事朝调解者或从调解者向同事建立,这两个方向上的依赖都可以使用abstractcolleague或abstractmediator中断。
对象不是孤立的,对象之间必须相互协作才能完成任务。虽然调解者模式可以限制对象之间的相互作用,但如果滥用,会致使编写聚合性类变得非常困难。举一个实用的例子,在领域驱动设计(domain-driven design)中的服务就是实体之间的调解者。再举一个php相关的例子,zend_form装饰和过滤功能实际上可以看作是zend_form_decorator和zend_filter实例之间的一个简单调解者,它们都使用zend_validate对象进行验证。
当调解者必须监听同事对象的事件时,它通常是作为观察者(observer)实现的,产生一个黑板(blackboard)对象,一些同事写,另一些同事就读。来自同事的事件被推向调解者,再由调解者将其转发给其它订阅的同事,同事之间不需要相互了解,这个架构成功用于随zend框架发布的dojo javascript库。这个模式的另一个好处是对象的变化包含在计算方法中,可以通过配置不同的调解者实现这一目标,但实例化相关对象将是一个松散的操作,不同容器和工厂之间的协作关系将是分散的。
参与者:
◆同事(colleague):重点是它的职责,它只与一个调解者mediator或abstractmediator通信。
◆调解者(mediator):协同多个colleagues(abstractcolleagues)共同工作。
◆abstractmediator,abstractcolleague:从这些角色的真实实现解耦的可选接口,可能不止一个abstractcolleague角色。
下面的代码实现了一个表单输入的过滤过程,类似于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);
}
} <pre class=php name="code"> /**
* colleague.
*/
class nullfilter implements filter
{
public function filter($value)
{
return $value ? $value : '';
}
}
/**
* colleague.
*/
class htmlentitiesfilter implements filter
{
public function filter($value)
{
return htmlentities($value);
}
}
</pre><pre class=php name="code"> /**
* 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";
</pre>
<pre></pre>
下一篇: 西兰花黄了还能吃吗