PHP设计模式

模式简介

什么是模式

在软件世界中,每个开发机构就像一个部落,而模式就是对部落的某种共同记忆的一种表现。—-Grady Booch,《J2EE核心模式》
模式便是特定环境下同类问题的一种解决方法 —-Gand of Four,《设计模式:可复用面向对象软件基础》
正如上面所暗示的,设计模式便是分析过的问题和问题解决方案所阐述的优秀实践。注意模式本质是自下而上的。它们来源于实践非空洞的理论。

模式概览

一个模式的核心由4个部分组成:命名、问题、解决方案和效果。

命名

命名非常重要。命名可以说丰富了程序员的语言,少许简短的文字便可表示相当复杂的问题和解决方案。命名必须兼顾简洁性和描述性。《设计模式》说道:找到一个好名字,成了我们在开发模式目录中最困难的部分之一。
Martin Flower 也赞同模式命名至关重要,因为模式的目的之一就是为开发者更加有效的交流提供词汇。

问题

无论解决方案如何优雅,问题以及问题发生的环境都是一个模式的基础。找出问题比使用模式目录中的解决方案更难。
模式会小心谨慎地描述问题的空间(发生的条件和环境)。问题会被置于环境中简明扼要地描述。问题会被分解成不同的细节和各种表现。

解决方案

解决方案最初和问题放在一起的。尽管代码有现成的,但是解决方案从来不是简单的复制哦,有可能实现上又上百种的细微差。
把一个比方:就像农作物播种操作,如果你盲目的遵循书本上的步骤,那么有可能到收货季节你有可能挨饿,以模式为基础,但又针 对各种情况随机应变的方案更加实用。虽然问题(农作物成长)的基本解决方案大致相同(播种、灌溉、收割),但是实际场景会有 各种因素,比如土壤类别、地理位置、土地方位、当地有害物等等。

效果

在设计代码的时候,你所做的每一个决定都会带来不同的结果。当然我们总是希望得到令人满意的针对问题的解决方案。解决方案一旦部署,理想情况下它也许非常适合与其他模式一同工作。但是也要留心是否会带来风险。

单例模式(Singleton)

概念

作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。

特点

  1. 一个类只有一个实例

  2. 它必须自行创建这个实例

  3. 必须自行向整个系统提供这个实例

三个要点

  1. 需要一个保存类的唯一私有静态变量
1
private static $_instance;
  1. 构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义
1
2
3
4
5
6
7
private function __construct(){
$this->_db = mysql_connect('xxxx');
}

private function __clone(){
//覆盖__clone()方法,禁止克隆
}
  1. 必须提供一个访问这个实例的公共的静态方法(通常为getInstance方法),从而返回唯一实例的一个引用
1
2
3
4
5
6
public static function getInstance(){   
if(!(self::$_instance instanceof self)){
self::$_instance = new self();
}
return self::$_instance;
}

应用场景

  1. 应用程序与数据库交互

    一个应用中会存在大量的数据库操作,比如过数据库句柄来连接数据库这一行为,使用单例模式可以避免大量的new操作,因为每一次new操作都会消耗内存资源和系统资源。

  2. 控制配置信息

    如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现。

代码实现

  1. 普通例子(不使用单例模式)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ......

    //初始化一个数据库句柄
    $db = new DB(...);

    //添加用户信息
    $db->addUserInfo(...);

    ......

    //在函数中访问数据库,查找用户信息
    function getUserInfo(){
    $db = new DB(...);//再次new 数据库类,和数据库建立连接
    $db = query(....);//根据查询语句访问数据库
    }
  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
32
class DB{

private $_db;
private static $_instance;

private function __construct(...){
$this->_db = mysql_connect(...);//mysql
}

private function __clone() {}; //覆盖__clone()方法,禁止克隆

public static function getInstance(){
if(! (self::$_instance instanceof self) ) {
self::$_instance = new self();
}
return self::$_instance;
}

public function addUserInfo(...){
//实现mysql语句
}

public function getUserInfo(...){
//实现mysql语句
}

}

//test
$db = DB::getInstance();
$db->addUserInfo(...);
$db->getUserInfo(...);

完整例子

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
class db {
public $conn;
public static $sql;
public static $instance = null;

private function __construct() {
require_once('db.config.php');
$this->conn = mysql_connect($db['host'], $db['user'], $db['password']);
if (!mysql_select_db($db['database'], $this->conn)) {
echo "失败";
};
mysql_query('set names utf8', $this->conn);
}

public static function getInstance() {
if (is_null(self::$instance)) {
self::$instance = new db;
}
return self::$instance;
}

/**
* 查询数据库
*/

public function select($table, $condition = array(), $field = array()) {
$where = '';
if (!empty($condition)) {

foreach ($condition as $k => $v) {
$where .= $k . "='" . $v . "' and ";
}
$where = 'where ' . $where . '1=1';
}
$fieldstr = '';
if (!empty($field)) {

foreach ($field as $k => $v) {
$fieldstr .= $v . ',';
}
$fieldstr = rtrim($fieldstr, ',');
} else {
$fieldstr = '*';
}
self::$sql = "select {$fieldstr} from {$table} {$where}";
$result = mysql_query(self::$sql, $this->conn);
$resuleRow = array();
$i = 0;
while ($row = mysql_fetch_assoc($result)) {
foreach ($row as $k => $v) {
$resuleRow[$i][$k] = $v;
}
$i++;
}
return $resuleRow;
}

/**
* 添加一条记录
*/

public function insert($table, $data) {
$values = '';
$datas = '';
foreach ($data as $k => $v) {
$values .= $k . ',';
$datas .= "'$v'" . ',';
}
$values = rtrim($values, ',');
$datas = rtrim($datas, ',');
self::$sql = "INSERT INTO {$table} ({$values}) VALUES ({$datas})";
if (mysql_query(self::$sql)) {
return mysql_insert_id();
} else {
return false;
};
}

/**
* 修改一条记录
*/

public function update($table, $data, $condition = array()) {
$where = '';
if (!empty($condition)) {

foreach ($condition as $k => $v) {
$where .= $k . "='" . $v . "' and ";
}
$where = 'where ' . $where . '1=1';
}
$updatastr = '';
if (!empty($data)) {
foreach ($data as $k => $v) {
$updatastr .= $k . "='" . $v . "',";
}
$updatastr = 'set ' . rtrim($updatastr, ',');
}
self::$sql = "update {$table} {$updatastr} {$where}";
return mysql_query(self::$sql);
}

/**
* 删除记录
*/

public function delete($table, $condition) {
$where = '';
if (!empty($condition)) {

foreach ($condition as $k => $v) {
$where .= $k . "='" . $v . "' and ";
}
$where = 'where ' . $where . '1=1';
}
self::$sql = "delete from {$table} {$where}";
return mysql_query(self::$sql);

}

public static function getLastSql() {
echo self::$sql;
}


}

$db = db::getInstance();
//$list = $db->select('demo',array('name'=>'tom','password'=>'ds'),array('name','password'));
//echo $db->insert('demo',array('name'=>'最近你啦','password'=>'123'));
//echo $db->update('demo',array("name"=>'xxx',"password"=>'123'),array('id'=>1));
echo $db->delete('demo', array('id' => '2'));
db::getLastSql();
echo "<pre>";

工厂方法模式(FactoryMethod)

抽象工厂模式(AbstractFactory)

适配器模式

策略模式

观察者模式

原型模式(Prototype)

装饰模式(Decorator)

迭代器模式

代理模式

组合模式(Composite)

外观模式(Facade)

综合实战