单例模式和工厂模式

职责和单例模式

  单例模式被认为是职责模式,这是由于它将建立对象的控制权委托到一个单一的访问点上.在任什么时候候,应用程序中都只有这个类仅有的一个实例存在.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');
View Code

工厂模式

  工厂类是指包含了一个专门用来建立其余对象的方法的类.工厂类在多态性编程实践中是相当重要的.它容许动态地替换类,修改配置,而且一般会使应用程序更加灵活.code

  一般,工厂模式有一个关键的构造,即根据通常原则被命名为factory的静态方法.然而,这只是一种原则,工厂方法能够任意命名.这个静态方法还能够接受任意数量的参数,而且必须返回一个对象.

基本的工厂类:

class MyObject{
    //对象将从工厂类返回
}
class MyFactory{
    public static function factory(){
        //返回对象的一个新实例
        return new MyObject();
    }
}

$instance = MyFactory::factory();
View Code

使用工厂类解析图像文件

<?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();
View Code

  上例中,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');
View Code

  以上代码建立一个DatabaseFactory类,它将会实例化并返回与IDatabaseBindings接口兼容的对象.应用程序将会根据IDatabaseBindings的规范来编写,而实现类将负责执行用来操做特定数据库的查询.

相关文章
相关标签/搜索