1. 工厂模式
工厂方法或者类生成对象,而不是在代码中直接new
1 |
|
2. 单例模式
使某个类的对象仅允许创建一个
1 |
|
3. 注册树模式
全局共享和交换对象
1 |
|
4. 适配器模式
适配器模式,可以将截然不同的函数接口封装成统一的API
如:mysql,mysqli,pdo3,类似cache适配器的场景,缓存有memcache,redis,file
1 |
|
5. 策略模式
- 将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,这种模式就是策略模式。
- 场景:假如一个点上网站系统,针对男女性用户要各自跳转到不同的商品类目,并且所有广告位展示不同的广告
- 应用:实现Ioc、依赖倒置和控制反转
策略定义:UserStrategy.php1
2
3
4
5
6
7
8
// 策略接口
interface UserStrategy
{
public function showAd();
public function showCategory();
}
男性策略:MaleUserStrategy.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MaleUserStrategy implements UserStrategy
{
public function showAd()
{
// TODO: Implement showAd() method.
echo "2017款男装";
}
public function showCategory()
{
// TODO: Implement showCategory() method.
echo "男装";
}
}
女性策略:FemaleUserStrategy.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class FemaleUserStrategy implements UserStrategy
{
public function showAd()
{
// TODO: Implement showAd() method.
echo "2017款女装";
}
public function showCategory()
{
// TODO: Implement showCategory() method.
echo "女装";
}
}
应用:index.php
1 |
|
6. 数据对象映射模式
- 数据对象映射模式,是将对象和数据存储映射起来,对一个对象的操作会映射到对数据存储的操作。
- 比如实现一个ORM类,将复杂的sql语句映射成对象属性的操作
数据表user:1
2
3
4
5
6CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL COMMENT 'ID',
`name` varchar(32) NOT NULL DEFAULT '' COMMENT '姓名',
`mobile` varchar(11) NOT NULL DEFAULT '' COMMENT '电话号码',
`regtime` int(11) NOT NULL DEFAULT '0' COMMENT '注册时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
实例代码, User.php:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class User
{
public $id;
public $name;
public $mobile;
public $regtime;
protected $db;
public function __construct($id)
{
// 根据id查询具体的某一行,然后赋值给对应的成员对象
}
public function __destruct()
{
// 根据成员变量,更新数据库
}
}
7. 观察者模式
- 观察者模式,当以个对象发生改变时,依赖他的对象全部会收到通知,并自动更新
- 场景:一个事件发生后,要执行一连串的更新操作。传统的编程方式,就是在事件的代码之后直接加入处理逻辑。当更新的逻辑增加之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件主体代码。
- 观察者模式实现了低耦合,非侵入式的通知和更新机制。
观察者Observer:1
2
3
4
5
6
interface Observer
{
public funciton update($event_info = null);
}
事件生产者EventGenerator:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
abstract class EventGenerator
{
private $observers = [];
public function addObserver(Observer $observer)
{
$this->observers[] = $observer;
}
public function notify()
{
if (count($this->observers) > 0) {
foreach ($this->observers as $observer) {
$observer->update();
}
}
}
}
应用:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Event extends EventGenerator
{
public function trigger()
{
echo "触发逻辑 \n";
// 通知所有观察者做更新操作
$this->notify();
}
}
class Observer1 implement Observer
{
public function update($event_info = null)
{
echo "我是观察者1,我收到更新动作通知,我要做些操作";
}
}
$event = new Event;
$event->addObserver(new Observer1);
$event->trigger();
8. 原型模式
- 与工厂模式作用类似,都是用来创建对象
- 与工厂模式的实现不用,原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象,这样就免去了类创建时重复的初始化操作
- 原型模式适合于大对象的创建,创建一个大对象要很大的开销,如果每次new就会消耗很大,原型模式仅需要内存拷贝即可。
1 |
|
9. 装饰器模式
- 装饰器模式(Decorator),可以动态地添加修改类的功能
- 一个类提供一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法
- 使用装饰器模式,仅需要在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性。
某一个功能类,如画一条线:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class DrawLine
{
private $char = '';
private $long = 0;
public function init($char = '_', $long = 10)
{
$this->char = $char;
$this->long = $long;
}
public function do()
{
echo str_repeat($this->char, $this->long);
}
}
以上类,想要修改线的样式,必须修改代码,首先必须给他添加具备使用装饰器的能力.
声明一个装饰器接口:1
2
3
4
5
6
7
8
9
interface DrawDecorator
{
public funciton beforeDraw();
public function afterDraw();
}
具备使用装饰器能力的画图类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
abstract draw
{
protected $decorators = [];
public function addDecorator(DrawDecorator $decorator)
{
$this->decorators[] = $decorator;
}
public function beforeDraw()
{
if (count($this->decorators) > 0) {
foreach ($this->decorators as $decorator) {
$decorator->beforeDraw();
}
}
}
public function afterDraw()
{
$decorators = array_reverse($this->decorators);
if (count($decorators) > 0) {
foreach ($decorators as $dec) {
$dec->afterDraw();
}
}
}
}
# 刚刚的画线类,继承draw
class DrawLine extends draw
{
private $char = '';
private $long = 0;
public function init($char = '_', $long = 10)
{
$this->char = $char;
$this->long = $long;
}
public function do()
{
$this->beforeDraw(); // 执行画线前动作
echo str_repeat($this->char, $this->long);
$this->afterDraw(); // 执行画线后动作
}
}
应用: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
# 实现一个装饰器
class ColorDrawDecorator implements DrawDecorator
{
private $color;
public function __constructor($color)
{
$this->color = $color;
}
public function beforeDraw()
{
echo "<div style='color:{$this->color}'>";
}
public function afterDraw()
{
echo "</div>";
}
}
$line = new DrawLine;
$line->init('-', 20);
// 实例化颜色装饰器,并且添加装饰器到line
$line->addDecorator(new ColorDrawDecoration('red'));
$line->do();
10. 迭代器模式
- 迭代器模式,在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素
- 相对于传统的编程模式,迭代器可以隐藏遍历元素的所需的操作。
- PHP中使用迭代器,只要实现接口Iterator
查询所有用户: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
class AllUser implements \Iterator
{
protected $ids;
protected $index;
protected $data;
public function __construct()
{
$db = Factory::getDatabase();
$result = $db->query("SELECT id FROM user", MYSQLI_ASSOC);
$this->ids = $result->fetch_all(MYSQLI_ASSOC);
}
public function next()
{
$this->index++;
}
public function valid()
{
return $this->index < count($this->ids);
}
public function rewind()
{
$this->index = 0;
}
public function key()
{
return $this->index;
}
public function current()
{
$id = $this->ids[$this->index]['id'];
return Factory::getUser($id);
}
}
11. 代理模式
- 在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行操作全部委派给代理对象,隐藏实体的具体实现细节。
- Proxy还可以与业务代码分离,部署到另一个的服务器。业务代码中通过RPC来委派任务。
12. 配置化
PHP中使用ArrayAccess实现配置文件的加载
Config.php1
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
class Config implements \ArrayAccess
{
protected $path;
protected $configs = [];
public function __construct($path)
{
$this->path = $path;
}
public function offsetExists($offset)
{
// TODO: Implement offsetExists() method.
}
public function offsetGet($offset)
{
if (empty($this->configs[$offset])) {
$file_path = $this->path . '/' . $offset . '.php';
$config = require $file_path;
$this->configs[$offset] = $config;
}
return $this->configs[$offset];
}
public function offsetSet($offset, $value)
{
// TODO: Implement offsetSet() method.
}
public function offsetUnset($offset)
{
// TODO: Implement offsetUnset() method.
}
}
有配置文件controller.php:1
2
3
4
5
6
7
8
9
10
# Config/controller.php
return [
'home' => [
'decorator' => [
'Imooc\Decorator\Template'
]
],
'default' => 'hello world'
];
应用:1
2
3
$config = new Config(__DIR__ . '/Config/controller.php');
var_dump($config['controller']);