前言
我们要给别人讲解一个问题的时候,最直观的方法莫过于用图形的方式去讲解,而不是枯燥的文字。毕竟我们还是个孩子的时候,图画更能给我们带来触动,而文字我们因为一些认知的问题会导致一些理解能力上的偏差。设计模式里面的UML类图就是可以让你给别人讲解设计理念的时候,不用再是枯燥的代码和文字,而是直接给别人用类图的形式来表达的一种方式。
为了方便大家了解,我会给出对应的类图,以及对应的代码实现,让大家有个初步的概念,方便大家来学习设计模式这枯燥的东西。
我们常见的几种关系:泛化(Generalization)、实现(Realization)、关联(Association)、聚合(Aggregation)、组合(Composition),依赖(Dependency)。
继承的类图
继承是我们在OOP中最常见的一种方式,让我们可以节约了不少的开发时间。继承也有一些别的文字描述方式:泛化。它是一种特殊的依赖。
继承就是指一个子类继承了另外一个的功能,并且可以增加它自己的新功能的能力。
表示方法:
继承使用空心箭头 + 实线表示。
示例:
1 |
|
2 | declare(strict_types=1); |
3 | |
4 | namespace Neilyoz\Example; |
5 | |
6 | abstract class BaseExample { |
7 | public abstract function method01(); |
8 | public abstract function method02(); |
9 | } |
10 | |
11 | class ExtendsExample extends BaseExample |
12 | { |
13 | public function method01() |
14 | { |
15 | // TODO: Implement method01() method. |
16 | } |
17 | |
18 | public function method02() |
19 | { |
20 | // TODO: Implement method02() method. |
21 | } |
22 | |
23 | public function method03() |
24 | { |
25 | |
26 | } |
27 | } |
实现的类型图
实现表示一个类(class)实现interface接口(可以实现多个接口)的功能。
表示方法:
使用空心三角形 + 虚线表示
示例:
我们都用过相机,有的相机只是可以拍照,但是有的相机例如拍立得,不仅可以拍照还能够打印出照片。

代码实现:
1 |
|
2 | |
3 | namespace Neilyoz\Example; |
4 | |
5 | interface Camera |
6 | { |
7 | public function photograph(); |
8 | } |
9 | |
10 | interface Printer |
11 | { |
12 | public function printer(); |
13 | } |
14 | |
15 | class Polaroid implements Camera, Printer |
16 | { |
17 | public function photograph() |
18 | { |
19 | echo "拍照" . PHP_EOL; |
20 | } |
21 | |
22 | public function printer() |
23 | { |
24 | echo "冲洗照片" . PHP_EOL; |
25 | } |
26 | } |
依赖的类图
介绍:
对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系。
使用依赖的类作为参数传入到对应方法中即可。
表示方法:
依赖关系用 虚线箭头 表示
示例:
人不管离不开空气和水对吧,我们依赖这两个东西生存,我们可以用类图来描述下。

代码实例:
1 |
|
2 | declare(strict_types=1); |
3 | |
4 | namespace Neilyoz\Example; |
5 | |
6 | class Oxygen |
7 | { |
8 | } |
9 | |
10 | class Water |
11 | { |
12 | } |
13 | |
14 | class Person |
15 | { |
16 | public function metabolism(Oxygen $oxygen, Water $water) |
17 | { |
18 | // 使用 氧气 水代谢 |
19 | } |
20 | } |
关联的类图
对于两个相对独立的对象,当一个对象的实例与另一个对象的一些特定实例存在固定的对应关系时,这两个对象之间为关联关系。
表示方法:
关联关系用实现箭头表示。
示例:
我们的农作物的成熟和天气气候有关系,当一个类需要知道另一个类时,可以用关联。

1 |
|
2 | declare(strict_types=1); |
3 | |
4 | class Climatic |
5 | { |
6 | public function getCondition() |
7 | { |
8 | return "秋天"; |
9 | } |
10 | } |
11 | |
12 | class Cropper |
13 | { |
14 | private Climatic $climaticConditions; |
15 | |
16 | public function __construct(Climatic $climatic) |
17 | { |
18 | $this->climaticConditions = $climatic; |
19 | } |
20 | |
21 | public function mature() |
22 | { |
23 | if ($this->climaticConditions->getCondition() === "秋天") { |
24 | echo "成熟了" . PHP_EOL; |
25 | return; |
26 | } |
27 | |
28 | echo "再等等" . PHP_EOL; |
29 | } |
30 | } |
聚合的类图
表示一种弱的”拥有”关系,即 has-a 关系,体现的是 A 对象可以包含 B 对象,但 B 对象不是 A 对象的一部分(可有可无的那种)。两个对象具有各自的生命周期。
表示方法:
聚合关系用 空心菱形 + 实线箭头 表示
示例:
大家都是人,是人就要混圈子,人的生命周期和圈子的生命是不一样的,有的人活100多岁,有的圈子没多久也会解散,但是圈子解散不影响人的生命。

1 |
|
2 | declare(strict_types=1); |
3 | |
4 | namespace Neilyoz\Example; |
5 | |
6 | class Person |
7 | { |
8 | private float $money; |
9 | |
10 | public function collectMoney(float $money) |
11 | { |
12 | $this->money += $money; |
13 | } |
14 | } |
15 | |
16 | class Group |
17 | { |
18 | private array $members = []; |
19 | |
20 | public function addMember(Person $person) |
21 | { |
22 | $this->members[] = $person; |
23 | } |
24 | |
25 | // 分钱 |
26 | public function cents() |
27 | { |
28 | array_map(function ($person) { |
29 | $person->collectMoney(rand(0, 100)); |
30 | }, $this->members); |
31 | } |
32 | } |
组合的类图
组合是一种强的‘拥有’关系,是一种contains-a的关系,体现了严格的部分和整体关系,部分和整体的生命周期一样。
表示方法:
组合关系用 实心的菱形+实线箭头 表示,还可以使用连线两端的数字表示某一端有几个实例。
示例:
一个男人必须有个大头还必须有个小头才能算完整吧。这种就提现了我们的强拥有关系。

1 |
|
2 | declare(strict_types=1); |
3 | |
4 | class BigHead |
5 | { |
6 | } |
7 | |
8 | class SmallHead |
9 | { |
10 | |
11 | } |
12 | |
13 | class Man |
14 | { |
15 | private BigHead $bigHead; |
16 | private SmallHead $smallHead; |
17 | |
18 | public function __construct() |
19 | { |
20 | // 代码中这里是我们固定不可替换的 |
21 | $this->bigHead = new BigHead(); |
22 | $this->smallHead = new SmallHead(); |
23 | } |
24 | } |
总结
其实UML类图的形式复杂起来也很复杂,但是有这些基础的构图,我们无非就是搭积木而已。Peace!!!