作者:老王
前些天我写了一篇《
PHP实现透明化事务处理》,讨论了如何利用装饰模式实现事务处理。如果具体点说,它是一个透明的装饰模式,因为装饰类和被装饰类实现了共同的接口。可惜当梦想照进现实的时候,我们猛然发现纯粹透明的装饰模式并不多,因为既然我们的类需要被“装饰”,很多时候就不可避免的要引入一些新方法,这些方法在原有的接口里是没有定义过的,对于这种情况,我们称之为半透明的装饰模式。
啥也不说了,直接上干货:
######################################################################
abstract class Behavior {
protected $chain;
public function __construct($chain) {
$this->chain = $chain;
}
public function getChain() {
return $this->chain;
}
public function __call($name, $param) {
return call_user_func_array(array($this->getChain(), $name), $param);
}
}
abstract class Model {
protected $wrappers;
public function getWrappers() {
return $this->wrappers;
}
}
######################################################################
class FooBehavior extends Behavior {
public function foo() {
echo "FooBehavior::foo\r\n<br />";
}
public function foobar() {
echo "FooBehavior::foobar begin\r\n<br />";
$this->getChain()->foobar();
echo "FooBehavior::foobar end\r\n<br />";
}
}
class BarBehavior extends Behavior {
public function bar() {
echo "BarBehavior::bar\r\n<br />";
}
public function foobar() {
echo "BarBehavior::foobar begin\r\n<br />";
$this->getChain()->foobar();
echo "BarBehavior::foobar end\r\n<br />";
}
}
######################################################################
class SomeModel extends Model {
protected $wrappers = array('foo', 'bar');
public function some() {
echo "SomeModel::some\r\n<br />";
}
public function foobar() {
echo "SomeModel::foobar\r\n<br />";
}
}
######################################################################
$model = new SomeModel();
$wrappers = $model->getWrappers();
for ($i = count($wrappers) - 1; $i >= 0; $i--) {
$class = ucfirst($wrappers[$i] . 'Behavior');
$model = new $class($model);
}
$model->foo();
$model->bar();
$model->foobar();
$model->some();
######################################################################
注释:
FooBehavior,BarBehavior是装饰类
SomeModel是被装饰类
foo, bar是装饰类新添加的方法
foobar是装饰类和被装饰类共同实现的方法
some是被装饰类原有的方法
运行上面的代码,你会得到如下结果:
FooBehavior::foo
BarBehavior::bar
FooBehavior::foobar begin
BarBehavior::foobar begin
SomeModel::foobar
BarBehavior::foobar end
FooBehavior::foobar end
SomeModel::some
你能看到我们既可以通过装饰添加新方法,而且还可以修饰已有的方法,实现类似before/after这样的回调函数的效果,甚至你可以通过装饰类置换掉被装饰类的某个方法,至于置换的方法,在上面代码里并没有演示,但其实方法很简单,只要在装饰类里不再传递chain即可。
装饰模式的作用那是相当强啊!