老王的BLOG上有篇帖子”PHP实现透明化事务处理“,谈到了装饰模式(包装模式),感觉受到很大启发,
经过一番胡思乱想后,最终结合PHP的特点,用以下方式实现可能最好,这个设计完全是独自想到的,没参考任何先人的思想,难免有不足之处,欢迎指正!
<?php
class FooAction {
public function execute() {
echo "<br />\r\n";
echo "FooAction::execute()<br />\r\n";
echo "<br />\r\n";
}
}
abstract class WrapperBehavior {
abstract public function before();
abstract public function after();
public function getName() {
return get_class($this);
}
}
class Authorization extends WrapperBehavior {
public function before() {
echo "Authorization begin<br />\r\n";
}
public function after() {
echo "Authorization end<br />\r\n";
}
}
class Transaction extends WrapperBehavior {
public function before() {
echo "Transaction begin<br />\r\n";
}
public function after() {
echo "Transaction end<br />\r\n";
}
}
class Wrapper {
protected $_srcObj = null;
protected $_wrapperBehaviors = array();
public function __construct($obj) {
$this->_srcObj = $obj;
}
public function add($srcMethod, $wrapperBehavior) {
$this->_wrapperBehaviors[$srcMethod][$wrapperBehavior->getName()] = $wrapperBehavior;
}
public function __call($method, $args) {
if (! method_exists($this->_srcObj, $method)) {
throw new Exception("The method {$method} not exists");
}
//before
foreach (array_reverse($this->_wrapperBehaviors[$method]) as $behavior) {
$behavior->before();
}
call_user_func_array(array(&$this->_srcObj, $method), $args); //用反射可能更好
//end
foreach ($this->_wrapperBehaviors[$method] as $behavior) {
$behavior->after();
}
}
}
$action = new FooAction();
$wrapper = new Wrapper($action);
$wrapper->add('execute', new Transaction());
$wrapper->add('execute', new Authorization());
$wrapper->execute();