最近读到一篇文章 Learning programming is different from learning a programming language,深有感触,特别是对整个互联网开发行业来说御剑术万剑诀两种思考方式是完全不同的。

设计模式的基本思想

抽象类:事物/功能/模块的抽象,且只抽象事物/功能/模块的通用部分。
接口:动作/行为/功能的抽象。
行为类:一般实例化接口,由于不同的功能会有不同的实现,所以将基本的共同点提取出来,实例化中只实现功能的不同部分。
设计原则
- 找到程序中的不同的部分,将他们独立出来,并且将相同部分写在一起。
- 行为是针对接口编程,而不是针对实现编程,接口则是针对抽象类的编程。
- 多用组合,少用继承。

Modules

Modules with UML

本文会提及的常见设计模式

  • 工厂模式
  • 装饰器模式
  • 观察者模式
  • 策略模式
  • 适配器模式
  • 原型模式
  • 注册模式
  • 单例模式

文字描述往往非常不能完整体现出来,我会在简单的文字描述后添加上一波代码,相对于文字来说,还是代码更容易被理解吧
Modules with UML

工厂模式

工厂模式是为了避免底层代码调整之后,会波及大片的代码区域。通过工厂方法来做底层与顶层代码的一个承接,保证代码的高可读性和高可改写,但是会创建一部分冗余代码。

底层代码:比如数据库数据操作,底层逻辑等,一般都是以一个单类的形式出现,不会有其他的操作。

工厂方法:底层类的实例化以及对数据的简单格式化,一般是以一个单独类的形式出现,不存在其他操作。

顶层代码:对数据进行逻辑操作,并格式化返回,只调用工厂方法即可,不需要了解底层的实现。

底层代码实例

1
2
3
4
5
6
7
8
9
<?php

class Base {

static function test() {
echo __FILE__;
}

}

工厂方法实例

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

class Factory {
/*
* 如果某个类在很多的文件中都new ClassName(),那么万一这个类的名字发生变更或者参数发生变化
* 如果不使用工厂模式,就需要修改每一个PHP代码
* 使用了工厂模式之后,只需要修改工厂类或者方法就可以了。
*/
static function getFile() {
$test1 = new Base();
return $test1;
}
}

顶层代码实例

1
2
3
4
5
6
7
8
9
10
11
12
<?php

spl_autoload_register('autoloadFunc');

$rst = Factory::getFile();
$rst->test();

function autoloadFunc($class) {
$dir = __DIR__;
$requireFile = $dir . '/' . $class . '.php';
require $requireFile;
}

factory pattern

装饰器模式

传统的编程模式,如果要在类中实现一个新的功能,可以通过集成的方式来实现。

而装饰器模式,可以在类中动态地添加额外的功能。

即底层类的只提供具体的业务流程,并不存在具体的逻辑代码,逻辑只会出现在继承后的子类当中,这样大大增加了系统的灵活性。

Loader
加载器,主要依靠spl_autoload_register()函数来实现,可自动引入所需文件/函数。

1
2
3
4
5
6
7
8
9
<?php

spl_autoload_register('loadfunc');

function loadfunc($class) {
$dir = __DIR__;
$file = $dir . '/' . $class . '.php';
require $file;
}

基本操作类
基类,通过基类设置了整个功能的核心执行流程,但不会去考虑逻辑执行的细枝末节。

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
<?php

require_once "Loader.php";

class Base {

protected $dect = array();

public function output() {
$this->before();
$this->after();
}

public function addDecorator(Decorator $decorator) {
$this->dect[] = $decorator;
}

protected function before() {
foreach ($this->dect as $decorator) {
$decorator->before();
}
}

protected function after() {
$temp = array_reverse($this->dect); // 后进先出(先进后出)的规则
foreach ($this->dect as $decorator) {
$decorator->after();
}
}
}

装饰器接口
定义了装饰器要有哪些功能。

1
2
3
4
5
6
7
8
9
10
<?php

require_once 'Loader.php';

interface Decorator {

function before();
function after();

}

装饰器1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

require_once "Loader.php";

class WallDecorator implements Decorator {

protected $wall;

function __construct($size) {
$this->wall = $size;
}

function before() {
echo "White painting ". $size;
}

function after() {
echo "area on the wall's center. \n";
}

}

装饰器2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

require_once "Loader.php";

class BrickDecorator implements Decorator {

protected $brick;

function __construct($size) {
$this->brick = $size;
}

function before() {
echo "Need ". $size . " brick cramm this room";
}

function after() {
echo " as floor. \n";
}

}

执行/调用

1
2
3
4
5
6
7
8
<?php

require_once "Loader.php";

$d = new Base;
$d->addDecorator(new WallDecorator('200*400'));
$d->addDecorator(new BrickDecorator('50*50'));
$d->output();