在面向对象中,一个对象只负责一个特定的任务通常是一种很好的选择。例如:你只想让一个对象去访问数据库。单例模式是一种职责模式,他将创建的对象委托到单一的访问点上。在任何时候,应用程序都只有这个类仅有的一个势力存在。这可以防止我们去打开数据库的多个链接或者不必要的使用多余的系统资源。在更加复杂的系统中,单例模式在维持应用程序状态同步方面也很重要。
使用单例模式前后内存对比:
对比两张内存图的结构,我们可以了解以下信息:
1.没有使用单例模式的构造图很混乱。
2.没有使用单例模式的数据库连接对象会随着系统的扩展二变多。
3.没有使用单例模式的数据库链接因为有多个对象操作不同的SQL,可能会导致业务逻辑的异常或者是同步的异常。
下面通过使用单例模式实现数据库连接操作:
单例类所需的三个公共元素:
1.必须拥有一个构造方法,并且必须被标记为private;
2.拥有一个保存类的实例的静态成员属性(字段);
3.拥有一个访问这个实例的公共的静态方法。
编码实现单例模式:
文件列表如下:
├── Action.class.php 继承自DB,给具体业务类做继承
├── Article.class.php 业务:文章类
├── client.php 系统入口
├── DB.class.php 数据库类:实现单例
├── Photo.class.php 业务:相册类
└── User.class.php 业务:用户类
Action.class.php
<?php
abstract class Action{
protected $_db;
public function __construct(){
$this->_db = DB::getInstance();
}
abstract public function query($_sql);
}
Article.class.php
<?php
class Article extends Action{
public function query($_sql){
return $this->_db->query($_sql);
}
}
client.php
<?php
require 'DB.class.php';
require 'Action.class.php';
require 'Article.class.php';
require 'Photo.class.php';
require 'User.class.php';
$_article = new Article();
print_r($_article->query("SELECT * FROM cms_adver"));
echo "<br/>";
$_photo = new Photo();
print_r($_photo->query("SELECT * FROM cms_link"));
echo "<br/>";
$_user = new User();
print_r($_user->query("SELECT * FROM cms_user"));
echo "<br/>";
DB.class.php
<?php
class DB{
private $_db;
//静态是通过类::字段直接访问的,privavte表示外部不能访问
static private $_instance;
/**
*单例实现方法
*@decription 生成单例
*@param NULL
*/
static public function getInstance(){
//确保是实例化一次
if(!(self::$_instance instanceof self)){
self::$_instance = new self();
}
return self::$_instance;
}
//单一职责问题,私有化克隆
private function __clone(){}
/**
*构造方法
*@decription 数据库连接,并将对象存为私有属性
*@param NULL
*/
private function __construct(){
try{
$this->_db = new PDO('mysql:host=localhost;dbname=cms', 'root', '123456');
}catch(PDOException $e){
exit($e->getMessage());
}
}
/**
*查询方法
*@decription 根据sql语句进行查询
*@param $_sql
*/
public function query($_sql){
return $this->_db->query($_sql);
}
}
Photo.class.php
<?php
class Photo extends Action{
public function query($_sql){
return $this->_db->query($_sql);
}
}
User.class.php
<?php
class User extends Action{
public function query($_sql){
return $this->_db->query($_sql);
}
}
结论:单例模式可以很好地替代全局变量。但该模式还存在有依赖性,所以在生产使用中要注意其高内聚,低耦合。