组合模式

定义

组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性

主要角色

  • 抽象组件(Component)角色:抽象角色,给参加组合的对象规定一个接口。在适当的情况下,实现所有类共有接口的缺省行为。声明一个接口用于访问和管理Component的子组件
  • 树叶组件(Leaf)角色:在组合中表示叶节点对象,叶节点没有子节点。在组合中定义图元对象的行为。
  • 树枝组件(Composite)角色:存储子部件。定义有子部件的那些部件的行为。在Component接口中实现与子部件有关的操作。

适用性

  • 你想表示对象的部分-整体层次结构。
  • 你希望用户忽略组合对象和单个对象的不同,用户将统一地使用组合结构中的所有对象。

一句话理解

将树状结构中的叶子可以通过自己组合成所需要的一个集合

比如公司下有多个部门,多个部门可以理解为多个叶子,可以通过自己组合部门,组成一个你需要使用的部门集合

比如一个游戏里的军队,多种士兵类型就是多个叶子,可以组合成自己需要的部队

实例

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<?php
/**
* Created by PhpStorm.
* User: Livfer
* Desc:
* Date: 2019/9/17
* Time: 11:11
*/

/**
* 异常类
* Class UnitException
*/
class UnitException extends Exception
{
}

/**
* 战斗单元抽象类
* Class Unit
*/
abstract class Unit
{

/**
* 添加具体战斗单元
* @param Unit $unit
* @return mixed
* @throws UnitException
*/
public function addUnit(Unit $unit)
{
throw new UnitException(get_class($this) . 'is the leaf node');
}

/**
* 移除具体战斗单元
* @param Unit $unit
* @return mixed
* @throws UnitException
*/
public function removeUnit(Unit $unit)
{
throw new UnitException(get_class($this) . 'is the leaf node');
}

/**
* 战斗单元伤害
* @return mixed
*/
abstract function bombardStrength();
}

/**
* 射手
* Class Archer
*/
class Archer extends Unit
{
/**
* 战斗单元伤害
* @return mixed
*/
function bombardStrength()
{
// TODO: Implement bombardStrength() method.
return 3;
}
}

/**
* 激光炮
* Class LaserCannonUnit
*/
class LaserCannonUnit extends Unit
{
public function bombardStrength()
{
// TODO: Implement bombardStrength() method.
return 10;
}
}

/**
* 军队
* Class Army
*/
class Army extends Unit
{
/**
* 添加的战斗单元集合
* @var
*/
protected $units = [];

public function addUnit(Unit $unit)
{
if (in_array($unit, $this->units, true)) {
return true;
}
$this->units[] = $unit;
return true;
}

public function removeUnit(Unit $unit)
{
$this->units = array_udiff($this->units, (array)$unit, function ($a, $b) {
return ($a === $b) ? 0 : 1;
});
}

/**
* 战斗单元伤害
* @return mixed
*/
function bombardStrength()
{
// TODO: Implement bombardStrength() method.
$hurt = 0;
foreach ($this->units as $unit) {
$hurt += $unit->bombardStrength();
}
return $hurt;
}
}


/**
* 创建我军
*/
$myArmy = new Army();
$myArmy->addUnit(new Archer());
$myArmy->addUnit(new Archer());
$myArmy->addUnit(new LaserCannonUnit());
echo '我军军力: '.$myHurt = $myArmy->bombardStrength();

/**
* 创建敌军
*/
$enemy = new Army();
$enemy->addUnit(new Archer());
$enemy->addUnit(new Archer());
$enemyHurt = $enemy->bombardStrength();
echo '敌军军力: '.$enemyHurt;

参考

[设计模式详解以及PHP实现][http://yansu.org/2014/04/19/design-patterns-of-php.html]