什么是单例模式

含义

单例模式是一种对象的创建模式,它用来确保某一个类只有一个实例,而且自行实例化并向整个系统全局的提供这个实例。

单例模式的特点

1、有一个保存类的唯一实例的静态成员变量

2、有一个定义为私有的构造函数,表明这个类是不可能形成实例的,防止出现这个类有多个实例的情况出现(有时也可添加个声明为私有的克隆函数)。

3、提供一个能访问这个实例的声明为公共的静态方法(通常为getInstance方法),用来作为返回唯一实例的引用。

具体实现代码:

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

class Preferences {
private $props = array();
private static $instance;
private function __construct(){

}
private function __clone(){};
public static function getInstance(){
if(empty(self::$instance)){
self::$instance = new Preferences();
}
return self::$instance;
}
public function setProperty($key,$val){
$this->props[$key] = $val;
}
public function getProperty($key){
return $this->props[$key];
}

}

//调用单例
$pref = Preferences::getInstance();
$pref->setProperty('name','cjhlfy');
unset($pref);
$pref2 = Preferences::getInstance();
echo $pref2->getProperty('name'); //name的属性值不会丢失,因为实例引用 $instance是静态属性

为什么要用单例模式

全局变量是面向对象程序员遇到的引发bug的主要原因之一,这是因为全局变量将捆绑于特定的环境,破坏了封装。如果新的应用程序无法保证一开始就定义了相同的全局变量,那么一个依赖于全局变量的类就无法就无法从一个应用程序中提取出来并应用到新的应用程序中。所以单例模式是一种对于全局变量的改进。

不过,单例模式的使用也有不利的地方,它可能导致很难调试的依赖关系。如果改变一个实例,那么所有使用改单例的类可能都会受到影响。当单例被使用时,依赖便会隐藏在方法内部,而且并不会出现在方法声明里。这使得系统中的依赖关系更难以追踪,因此需要谨慎小心的部署单例类

单例模式应用

应用场合

1、应用程序与数据库的交互

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

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
33
34
class DB  {      
private $db;
private static $instance;
private function __construct(){
//进行数据库连接
}
private function __clone() {

};
public static function getInstance(){
if(empty(self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
//数据库查询操作
public function select(){
//...
}
//数据库插入操作
public function insert(){
//...
}}
//数据库编辑操作
public function update(){
//...
}}

//获取数据库单例类实例化之后,便可对数据库进行操作

$db = DB::getInstance();
$db->select();
$db->insert();
$db->update();

单例模式的总结就到这里。

参考:《面向对象、模式与实践》