代码片段(3)[全屏查看所有代码]
1. [代码]核心类
01 |
<?php |
02 |
03 |
/** |
04 |
* 包装器(Wrapper).
|
05 |
* Wrapper是一个AOP_LIKE的实现. 也可以看作监听者模式的实现.
|
06 |
* 一个Wrapper报装了一个对象(source). source可以是任意对象(不包括数组及原子类型),甚至是一个Wrapper.
|
07 |
*
|
08 |
* 包装器可以任意添加饰品(Decoration).通过Wrapper调用source的函数的流程将是:
|
09 |
* unpacking --> teardown --> open --> setup --> packing.
|
10 |
*
|
11 |
* 例如调用source->doXX(),各个流程将是:
|
12 |
* unpacking: 解包. 这是调用任意source的函数都会调用的方法;
|
13 |
* teardown: 撕掉饰品. 对于Wrapper中的每个Decoration,调用其before()函数;
|
14 |
* open: 真正调用source->doXX()函数;
|
15 |
* setup: 重新贴上饰品. 对于Wrapper中的每个Decoration,调用其after()函数;
|
16 |
* packing: 重新打包. 这是调用任意source的函数都会调用的方法;
|
17 |
*
|
18 |
*/
|
19 |
class Wrapper{
|
20 |
private $source;
|
21 |
22 |
/**
|
23 |
* @var bool
|
24 |
*/
|
25 |
private $undecorated;
|
26 |
27 |
/**
|
28 |
* @var array[Decoration]
|
29 |
*/
|
30 |
private $decorations=array();
|
31 |
32 |
public function __construct($source){
|
33 |
$this->source = $source;
|
34 |
}
|
35 |
36 |
public function __call($name,$parameters){
|
37 |
$this->unpacking($name,$parameters);
|
38 |
$this->tearDown($name,$parameters);
|
39 |
40 |
// opening
|
41 |
if(method_exists($this->source, $name)){
|
42 |
$retval = call_user_func_array(array($this->source,$name),$parameters);
|
43 |
}
|
44 |
45 |
$this->setup($retval,$name,$parameters);
|
46 |
$this->packing($retval,$name,$parameters);
|
47 |
48 |
return $retval;
|
49 |
}
|
50 |
51 |
public function unpacking($name,$parameters){
|
52 |
}
|
53 |
54 |
public function packing($name,$parameters){
|
55 |
}
|
56 |
57 |
public function tearDown($name,$parameters){
|
58 |
if($this->undecorated){
|
59 |
return;
|
60 |
}
|
61 |
foreach ($this->decorations as $d){
|
62 |
$d->before($name,$parameters);
|
63 |
}
|
64 |
}
|
65 |
66 |
public function setup($retval,$name,$parameters){
|
67 |
if($this->undecorated){
|
68 |
return ;
|
69 |
}
|
70 |
foreach ($this->decorations as $d){
|
71 |
$d->after($retval,$name,$parameters);
|
72 |
}
|
73 |
}
|
74 |
75 |
public function decarate($decoration){
|
76 |
$this->decorations[] = $decoration;
|
77 |
}
|
78 |
79 |
80 |
81 |
public static function wrap($source){
|
82 |
// wrap the source
|
83 |
$wrapperConfig = app()->wrappers[get_class($source)];
|
84 |
if($wrapperConfig){
|
85 |
$wrapperClass = $wrapperConfig['class'];
|
86 |
$wrapper = new $wrapperClass($source);
|
87 |
88 |
foreach ($wrapperConfig['decorations'] as $item){
|
89 |
$decoration = new $item;
|
90 |
$wrapper->decarate($decoration);
|
91 |
}
|
92 |
}
|
93 |
return $wrapper?$wrapper:$source;
|
94 |
}
|
95 |
96 |
} |
97 |
98 |
?> |
2. [代码]配置
01 |
'wrappers'=>array(
|
02 |
'ContentService'=>array(
|
03 |
'class'=>'ContentWrapper',
|
04 |
'decorations'=>array(
|
05 |
'DasaiContentDecoration',
|
06 |
)
|
07 |
),
|
08 |
'AOPWorker'=>array(//for test
|
09 |
'class'=>'DiagnosisWrapper',
|
10 |
'decorations'=>array(
|
11 |
'DasaiDiagnosisDecoration'
|
12 |
),
|
13 |
),
|
14 |
), |
3. [代码]测试代码
01 |
class AOPWorker{
|
02 |
public function testAOP(){
|
03 |
Debugger::print_r(
|
04 |
"
工人:我要做一大堆操作了
|
05 |
工人:... ...
|
06 |
工人:好了 做完了
");
|
07 |
return 'OK';
|
08 |
}
|
09 |
10 |
} |
11 |
12 |
13 |
public function testAOP(){// test aop 测试入口
|
14 |
$aop = Wrapper::wrap(new AOPWorker());
|
15 |
$aop->testAOP(33347);
|
16 |
} |
17 |
18 |
19 |
20 |
class DiagnosisWrapper extends Wrapper{
|
21 |
22 |
public function unpacking($name, $parameters){
|
23 |
echo "
DiagnosisWrapper:喂,有人调用$name,我要解包了.
";
|
24 |
}
|
25 |
26 |
27 |
public function packing($retval,$name, $parameters){
|
28 |
echo "
DiagnosisWrapper:喂,调用$name,结果为$retval,重新打包好了.
";
|
29 |
}
|
30 |
} |
31 |
32 |
33 |
34 |
class DasaiDiagnosisDecoration extends Decoration {
|
35 |
public function before($name,$parameters){
|
36 |
echo "
DasaiDiagnosisDecoration:开始调用$name,已经告诉张三李四了.
";
|
37 |
}
|
38 |
39 |
public function after($retval,$name,$parameters){
|
40 |
echo "
DasaiDiagnosisDecoration:结束调用$name,告诉霍金和Sheldon了.
";
|
41 |
}
|
42 |
} |