设计模式(二):组合模式、装饰模式、策略模式

0

继续学习了书本上的内容,大多数都是从代码上理解的,所以看代码很重要,要耐心看完书本上的demo

1 组合模式

将一组对象组合成为可像单个对象一样被使用的结构。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// demo
// 以Unit Army Archer三个为例
// 部队单位
abstract class Unit {
function addUnit(Unit $unit) {
throw new Exception( get_calss($this)."is a leaf");;
}
function removeUnit(Unit $unit){
throw new Exception( get_calss($this)."is a leaf");
}
abstract function bombardStrength();
}
// 没有重写addUnit removeUnit 因此Archer不能add和remove
class Archer extends Unit {
function bombardStrength() {
return 4;
}
}
// ...class rider{}...其他需要组合的类
class Army extends Unit {
private $units = array();
function addUnit(Unit $unit) {
if ( in_array( $unit, $this->units, true) ) {
return;
}
$this->units[] = $unit;
}
function removeUnit(Unit $unit) {
$this->units = array_diff($this->units, array($unit));
}
function bombardStrength() {
$ret = 0;
// 逐级调用对象树的方法
foreach( $this->units as $unit) {
$ret += $unit->bombardStrength();
}
return $ret;
}
}
$army_1 = new Army();
$army_2 = new Army();
$army_1->addUnit(new Archer()); // 组合Archer这个类到army_1
$army_2->addUnit($army_1) // 组合army_1到army_2
// ...

2 装饰模式

将一个对象包装到具有相同接口的另一个对象中,因此可以在另一个对象中对添加行为,然后将方法传递调用。可以帮助聚合组件,解决继承体系上过多的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// demo
class RequestHelper{}
// 抽象基类
abstract class ProcessRequest {
abstract function process(RequestHelper $req);
}
// 具体组件
class MainProcess extends ProcessRequest{
function process(RequestHelper $req) {
print __class__.": doing something useful with request \n";
}
}
// 抽象装饰类
abstract class DecorateProcess extends ProcessRequest{
protected $processrequest;
function __construct(ProcessRequest $pr) {
$this->processrequest = $pr;
}
}
// 具体装饰类
class LogRequest extends DecorateProcess {
function process(RequestHelper $req) {
// 额外的行为
print __class__."logging request\n";
// 再将请求交给原对象
$this->processrequest->process($req);
}
}
// 多了一个类对MainProcess这个组件进行装饰,实现了额外的行为比如logging request。
$process = new LogRequest(new MainProcess());
$process->process(new RequestHelper());

3 策略模式

将类拆分为子类

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// demo
abstract class Question {
protected $prompt;
protected $marker;
function __construct ($prompt, Marker $marker) {
$this->marker = $marker;
$this->prompt = $prompt;
}
// 对策略对象方法调用
function mark($response) {
return $this->marker->mark($response);
}
}
class TextQuestion extends Question {
// 一个类 处理文本问题操作
}
// 抽象类
abstract class Marker {
protected $test;
function __construct($test) {
$this->test = $test;
}
abstract function mark($response);
}
// 匹配文本的策略类
class MatchMarker extends Marker {
function mark($response) {
return ($this->test == $response);
}
}
// MatchMarker对TextQuestion标记上了yes
$question = new TextQuestion('this is text?', new MatchMarker('yes'));
$question->mark('no'); // return false;
$question->mark('yes'); // return true;

demo 中 TextQuestion 通过 __construct 时的传入的策略对象,最后实际调用了策略对象里的方法。可以根据不同需求写 Marker。