PHP单例模式定义与使用实例详解


Posted in PHP onFebruary 06, 2017

本文实例讲述了PHP单例模式定义与使用。分享给大家供大家参考,具体如下:

先简单的介绍一下单例模式。单例模式就是在应用程序中保持某一个类实例只存在一个,而且不可以受外部环境的影响而生成这个类的第二个实例。它的优点,实际点见,如果在WEB开发中,保持单一个数据操作类实例的存在,可以减少不必要的多余连接数据库资源的消耗,对于大型的软件开发来说,可以使用单例来维持程序的状态,使不同操作实现同步,因为单例一直占据内存,而从不会有副本。

而对于PHP,使用单例最常用的场合莫过于写一个数据库操作类。不过在PHP中实现单例,有以下规则:

1)单例类必须拥有一个现式声明的构造函数,并且是私有的。

2)单例类必须有一个静态变量来存储类的实例,这样可以保持这个单例类就只有那么一个实例。

3)单例类必须提供一个静态方法,供其他所有的对象应用这个单例。

为什么要满足以上三个条件呢:

1)因为单例类在整个应用程序运行时,只能被创造一次,而且这种创造是不是通过外部调用而完成,而是自身完成。所以单例类是自己实例化自己,所以其构造函数必须是私有。任何其他外部对象都不可以再次构造一个单例类的副本。

2)因为单例类只能够自己实例化自己,而又要为所有外部应用提供自己的实例,所以类内部必须有一个可供外界访问,而又是唯一不变的访问存储对象点,所以要提供一个静态变量去存储单例类自己实例化自己的那个实例对象。

3)因为单例类的构造函数是私有的,所以单例类必须提供一个外部接口供外部环境调用单例类,所以必须有一个静态方法,它可以初始化单例类或者返回单例类的对象的引用。

一个简单的例子:

class DB{
   private $_link;
   //   保持单例类的静态变量
   static $_instance;
   //   私有的构造函数
   private function __construct(){
       $this->_link = @mysqli_connect(__HOST__, __USER__, __PASSWORD__, __DATABASE__);
       if(! ($this->_link)){
          echo 'Something wrong occurs on the database connection!';  
       }
   }
   //   防止单例类被克隆
   private function __clone(){}
   //   外界访问单例类实例的接口
   public static function getInstance(){
       if(! (self::$_instance instanceof self)){
          self::$_instance = new self();
       }
       return self::$_instance;
   }
}

注意,以上定义的一个 __clone() 函数,防止单例类对象被克隆。

以下也是一个简单的数据库操作类的单例,供参考:

class DB {
   /**
    * the database connection
    * @var   resource
    * @access private
    */
   private $_link;
   /**
    * the static instance of single db
    * @var   object
    * @access static
    */
   static $_instance;
   /**
    * construct the single object
    * @return null
    * @access private
    */
   private function __construct(){
       $this->_link = @mysqli_connect(__HOST__, __USER__, __PASSWORD__, __DATABASE__);
       if(! ($this->_link)){
          echo 'Something wrong occurs on the database connection!';  
       }
   }
   /**
    * empty clone
    * @return null
    * @access private
    */
   private function __clone(){}
   /**
    * for other object to get the instance of db
    * @return self::instance
    * @access public
    */
   public static function getInstance(){
       if(! (self::$_instance instanceof self)){
          self::$_instance = new self();
       }
       return self::$_instance;
   }
   /**
    * query
    * @param  sql string
    * @param  message string
    * @return   resource
    * @access public
    */
   public function query($sql,$message){
       $result = @mysqli_query($this->$_link, $sql) or die($message . mysqli_error($this->$_link));
       return $result;
   }
   /**
    * mysqli_num_rows
    * @param  result resource
    * @return   int
    * @access public
    */
   public function num($result){
       return @mysqli_num_rows($result);
   }
   /**
    * mysqli_fetch_array
    * @param  result resource
    * @return   array
    * @access public
    */
   public function fetchArr($result){
       return @mysqli_fetch_array($result);
   }
   /**
    * mysqli_insert_id
    * @return   int
    * @access public
    */
   public function last_id(){
       return @mysqli_insert_id($this->_link);   
   }
   /**
    * close the database connection
    * @param  result resource
    * @return   null
    * @access public
    */
   public function close(){
       @mysqli_close($this->_link);
   }
   /**
    * fetch once result from the specific sql query
    * @param  sql string
    * @param  message string
    * @return   array
    * @access public
    */
   public function fetchArrOnce($sql, $message){
       $result = $this->query($sql, $message);
       $row = $this->fetchArr($result);
       return $row;
   }
   /**
    * fetch all results from the specific sql query
    * @param  sql string
    * @param  message string
    * @return   array
    * @access public
    */
   public function fetchArrMore($sql, $message){
       $result = $this->query($sql, $message);
       $moreRow = array();
       while($row = $this->fetchArr($result)){
          $moreRow[] = $row;
       }
       return $moreRow;
   }
   /**
    * fetch the number of results from the specific sql query
    * @param  sql string
    * @param  message string
    * @return   array
    * @access public
    */
   public function fetchNum($sql, $message){
       $result = $this->query($sql, $message);
       $resultNum = $this->num($result);
       return $resultNum;
   }
   /**
    * mysqli_prepare
    * @param  sql string
    * @return   stmt object
    * @access public
    */
   public function prepare($sql){
       return @mysqli_prepare($this->_link, $sql);
   }
   /**
    * mysqli_stmt_execute
    * @param  stmt object
    * @param  message string
    * @return   bool
    * @access public
    */
   public function stmt_execute($stmt, $message){
       @mysqli_stmt_execute($stmt) or die($message . mysqli_error($this->_link));
   }
}

使用:

define("__HOST__", "localhost");
define("__USER__", "root");
define("__PASSWORD__", "");
define("__DATABASE__", "eee");
$db = DB::getInstance();

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
十天学会php之第五天
Oct 09 PHP
第十一节--重载
Nov 16 PHP
js和php邮箱地址验证的实现方法
Jan 09 PHP
php中判断数组相等的方法以及数组运算符介绍
Mar 30 PHP
PHP使用flock实现文件加锁的方法
Jul 01 PHP
php基本函数汇总
Jul 09 PHP
[原创]php常用字符串输出方法分析(echo,print,printf及sprintf)
Jul 09 PHP
php flush无效,IIS7下php实时输出的方法
Aug 25 PHP
Yii2中datetime类的使用
Dec 17 PHP
thinkPHP框架RBAC实现原理分析
Feb 01 PHP
php报错502badgateway解决方法
Oct 11 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
Apr 05 PHP
PHP第三方登录―QQ登录实现方法
Feb 06 #PHP
php计算给定日期所在周的开始日期和结束日期示例
Feb 06 #PHP
PHP实现判断数组是一维、二维或几维的方法
Feb 06 #PHP
php中get_magic_quotes_gpc()函数说明
Feb 06 #PHP
PHP数字前补0的自带函数sprintf 和number_format的用法(详解)
Feb 06 #PHP
浅谈php中fopen不能创建中文文件名文件的问题
Feb 06 #PHP
PHP 类与构造函数解析
Feb 06 #PHP
You might like
PHP substr 截取字符串出现乱码问题解决方法[utf8与gb2312]
2011/12/16 PHP
微信公众平台之快递查询功能用法实例
2015/04/14 PHP
php将金额数字转化为中文大写
2015/07/09 PHP
php简单统计在线人数的方法
2016/05/10 PHP
PHP完全二叉树定义与实现方法示例
2017/10/09 PHP
javascript下给元素添加事件的方法与代码
2007/08/13 Javascript
javascript 得到变量类型的函数
2010/05/19 Javascript
jquery 弹出层注册页面等(asp.net后台)
2010/06/17 Javascript
基于jquery实现漂亮的动态信息提示效果
2011/08/02 Javascript
JS定义类的六种方式详解
2016/05/12 Javascript
js删除数组元素、清空数组的简单方法(必看)
2016/07/27 Javascript
Highcharts学习之数据列
2016/08/03 Javascript
jQuery弹出div层过2秒自动消失
2016/11/29 Javascript
基于nodejs+express4.X实现文件下载的实例代码
2017/07/13 NodeJs
AjaxUpLoad.js实现文件上传
2018/03/05 Javascript
使用vue打包时vendor文件过大或者是app.js文件很大的问题
2018/06/29 Javascript
在vue中获取token,并将token写进header的方法
2018/09/26 Javascript
vue-cli3.X快速创建项目的方法步骤
2019/11/14 Javascript
[08:53]DOTA2每周TOP10 精彩击杀集锦vol.9
2014/06/26 DOTA
[40:03]Liquid vs Optic 2018国际邀请赛淘汰赛BO3 第一场 8.21
2018/08/22 DOTA
Python的条件语句与运算符优先级详解
2015/10/13 Python
Python实现采用进度条实时显示处理进度的方法
2017/12/19 Python
Python 多线程不加锁分块读取文件的方法
2018/12/11 Python
Python可以用来做什么
2020/11/23 Python
有原因的手表:Flex Watches
2019/03/23 全球购物
娱乐地球:Entertainment Earth
2020/01/08 全球购物
博士学位自我鉴定范文
2013/12/26 职场文书
网络优化专员求职信
2014/05/04 职场文书
测控技术自荐信
2014/06/05 职场文书
大二学生自我检讨书
2014/10/23 职场文书
2016年暑假学生家长评语
2015/12/01 职场文书
PyTorch 如何检查模型梯度是否可导
2021/06/05 Python
golang fmt格式“占位符”的实例用法详解
2021/07/04 Golang
用Python仅20行代码编写一个简单的端口扫描器
2022/04/08 Python
浅谈Redis缓冲区机制
2022/06/05 Redis
oracle设置密码复杂度及设置超时退出的功能
2022/06/28 Oracle