单例模式被认为是职责模式,这是由于它将建立对象的控制权委托到一个单一的访问点上.在任什么时候候,应用程序中都只有这个类仅有的一个实例存在.php
全部的单例类至少拥有如下三种公共元素:mysql
1.它们必须拥有一个构造函数,而且必须被标记为private.sql
2.它们拥有一个保存类的实例的静态成员变量.数据库
3.它们拥有一个访问这个实例的公共的静态方法.编程
和普通类不一样的是,单例类不能在其余类中直接实例化.单例类只能被其自身实例化.要得到这种限制效果,__contruct()方法必须被标记为private.若是试图用private构造函数构造一个类,就会获得一个可访问性级别的错误.ide
要让单例类起做用,就必须使其为其余类提供一个实例,用他调用各类方法.单例类不会建立实例副本,而是会向单例类内部存储的实例返回一个引用.结果是单例类不会重复占用内存和系统资源,从而让应用程序的其余部分更好地使用这些资源.做为这-模式的一部分,必须建立一个空的私有的__clone()方法,以防止对象被复制或者克隆.函数
返回实例引用的这个方法一般被命名为getInstance().这个方法必须是静态的,并且若是它尚未实例化,就必须进行实例化.getInstance()方法经过使用instanceof操做符和self关键字,能够检测到类是否已经被初始化.若是保存实例静态成员为空或者还不是类自身的一个实例,那么这个实例将会被建立并保存到存放实例的变量中.this
使用单例类:spa
class Database{ private $_db; static $_instance; private function __construct(){ $this->_db = pg_connect('dbname=example_db'); } private __clone(){}; public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self(); } return self::$_instance; } public function query($sql){ //使用$this->_db执行一个查询 return pg_query($this->_db,$sql); } } $db = Database::getInstance(); $db->query('SELECT * FROM example_table');
工厂类是指包含了一个专门用来建立其余对象的方法的类.工厂类在多态性编程实践中是相当重要的.它容许动态地替换类,修改配置,而且一般会使应用程序更加灵活.code
一般,工厂模式有一个关键的构造,即根据通常原则被命名为factory的静态方法.然而,这只是一种原则,工厂方法能够任意命名.这个静态方法还能够接受任意数量的参数,而且必须返回一个对象.
基本的工厂类:
class MyObject{ //对象将从工厂类返回 } class MyFactory{ public static function factory(){ //返回对象的一个新实例 return new MyObject(); } } $instance = MyFactory::factory();
使用工厂类解析图像文件
<?php interface IImage{ function getHeight(); function getWidth(); function getData(); } class Image_PNG implements IImage{ private $_width,$_height,$_data; public function __construct($file){ $this->_file = $file; $this->_parse(); } private function _parse(){ //完成PNG格式的解析工做 //并填充$_width,$_height和$_data } public function getWidth(){ return $this->_width; } public function getHeight(){ return $this->_height; } public function getData(){ return $this->_data; } } class Image_JPEG implements IImage{ private $_width,$_height,$_data; public function __construct($file){ $this->_file = $file; $this->_parse(); } private function _parse(){ //完成JPEG格式的解析工做 //并填充$_width,$_height和$_data } public function getWidth(){ return $this->_width; } public function getHeight(){ return $this->_height; } public function getData(){ return $this->_data; } } class ImageFactory{ public static function factory($file){ $pathParts = pathinfo($file); switch (strtolower($pathParts['extension'])) { case 'jpg': $ret = new Image_JPEG($file); break; case 'png': $ret = new Image_PNG($file); default: //有问题 } if($ret instanceof IImage){ return $ret; }else{ //有问题 } } } $image = ImageFactory::factory('/path/to/my.jpg'); //$image如今是Image_JPEG类的一个实例 echo $image->getWidth();
上例中,ImageFactory是工厂类,由于它返回了一个类的实例.类的类型是经过调用pathinfo()函数得到的文件拓展名类决定的.因为它是一个工厂类,产生的应用程序不须要知道这些图像解析的细节,须要知道的是工厂返回的对象支持IImage接口.
使用这一技术使得API更加容易调用,这是由于它只有一个类和一个方法.若是不使用工厂模式,API的调用者将须要决定应该调用的类,而后去调用某个特定的类,这样就须要对工厂的行为进行复制.
工厂类解决数据库可移植性问题
interface IDatabaseBindings{ public function userExists($email); } class PGSQL implements IDatabaseBindings{ protected $_connection; public function __construct(){ $this->_connection = pg_connect('dbname=example_db'); } public function userExists($email){ $emailEscaped = pg_escape_string($email); $query = "select 1 from users where email ='".$emailEscaped."'"; if($result = pg_query($query,$this->_connection)){ return (pg_num_rows($result) > 0)?true:false; }else{ return false; } } } class MYSQL implements IDatabaseBindings{ protected $_connection; public function __construct(){ $this->_connection = mysql_connect('localhost'); mysql_select_db('example_db',$this->_connection); } public function userExists($email){ $emailEscaped = mysql_real_escape_string($email); $query = "select 1 from users where email ='".$emailEscaped."'"; if($result = mysql_query($query,$this->_connection)){ return (mysql_num_rows($result) > 0)?true:false; }else{ return false; } } } class DatabaseFactory{ public static function factory(){ $type = loadtypefromconfigfile(); switch ($type) { case 'PGSQL': return new PGSQL(); break; case 'MYSQL': return new MYSQL(); break; } } } //---用法--- $db = DatabaseFactory::factory(); $db->userExists('person@example.com');
以上代码建立一个DatabaseFactory类,它将会实例化并返回与IDatabaseBindings接口兼容的对象.应用程序将会根据IDatabaseBindings的规范来编写,而实现类将负责执行用来操做特定数据库的查询.