在上一章中,我们介绍了PHP设计模式里面的工厂模式。工厂模式是一个可以批量创建对象实例的模式,但是有时候我们经常会遇到一个与此问题相反的场景,不需要创建很多的各种各样的对象,我们需要的是,只创建几个对象,很多情况下是只需要一个对象,然后在以后的程序中持续使用此对象。
?
例如,在 CMS 或者其它类似的管理系统中,经常使用到的数据库连接资源,这个资源只需要在程序启动的时候创建出来,并对其进行初始化,当程序结束的时候,断开数据库连接,将此资源销毁并回收。数据库连接通常是很消息资源的,CPU或者内存或者网络带宽等,如果每次需要使用此链接的时候都创建一次,使用完成后销毁,这样效率是极低的。如果可以将已经建立好的连接重新使用的话,就不要使用复制/粘贴的模式来实现代码复用了。
?
这正是本章中将要介绍的单件模式(Singleton Pattern)。维基百科给出的定义是:“单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。”
?
问题
?
这个类的行为很特殊,因为他在整个程序的生命周期呢,它的对象实例是独一无二的。当我们创建一个这样的实例后,它就是唯一的,不存在此类的第二个实例。
?
解决方案
?
我们首先想到的就是全局变量。但是经验告诉我们,尽量避免使用全局变量,但是也不尽然。
?
通常,使用全局变量被认为是坏习惯,这正是由于全局变量的非局部性:全局变量可能被从任何地方修改(除非位于保护内存中),也可能被任何地方所依赖。于是全局变量便拥有了建立相互依存关系的无限可能,而互相依存关系的建立会使得复杂度增加。然而,在少数情况下是适合使用全局变量的。例如,可以通过全局变量的使用来避免常用变量在一系列函数间的频繁传递。
?
为了防止产生此类的其他实例,通常需要将它的构造函数设置为 private 类型,禁止在类外创建此对象的实例。那么我们将如何构建此对象呢?通常我们需要一个构造该对象的方法,一般使用名为 getInstance() 的静态方法。
?
下面是一个例子:
?
class DbConn { function DbConn($fromGetInstance=false) { if (M_E != $fromGetInstance) { trigger_error("The DbConn class is a Singleton," ." please do not instantiate directly."); } } function &getInstance() { $key = "__some_unique_key_for_the_DbConn_instance__"; if (!(array_key_exists($key, $GLOBALS) && is_object($GLOBALS[$key]) && "dbconn" == get_class($GLOBALS[$key]) )) { $GLOBALS[$key] =& new DbConn(M_E); } return $GLOBALS[$key]; } }?
代码解释:
?
在此代码中,使用了 getInstance() 静态函数,在此函数中也使用了全局变量 $GLOBALS,当我们第二次创建此对象的时候首先进行判断该对象是否已经实例化,如果已经实例化,则不需要重复创建,只需要返回已经实例话的对象。
?
原文链接:http://tjwzjs.cn/news/knowledge/2012/1213/61.html