PHP设计模式浅析

工厂模式

提到的最多, 用途也最广. 简单说就是: 定义一个用户创建对象的接口. 把创建对象的过程封装起来. 

工厂类是指包含一个专门用来创建其他对象的方法的类,工厂类在多态性编程实践中是至关重要的,它允许动态的替换类,修改配置,通常会使应用程序更加灵活,熟练掌握工厂模式高级PHP开发人员是很重要的。

工厂模式通常用来返回符合类似接口的不同的类,工厂的一种常见用法就是创建多态的提供者,从而允许我们基于应用程序逻辑或者配置设置来决定应实例化哪一个类,例如,可以使用这样的提供者来扩展一个类,而不需要重构应用程序的其他部分,从而使用新的扩展后的名称 。

通常,工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,工厂方法可以任意命名,这个静态还可以接受任意数据的参数,必须返回一个对象。

【抽象工厂模式中主要角色】
抽象工厂(Abstract Factory)角色:它声明一个创建抽象产品对象的接口。通常以接口或抽象类实现,所有的具体工厂类必须实现这个接口或继承这个类。
具体工厂(Concrete Factory)角色:实现创建产品对象的操作。客户端直接调用这个角色创建产品的实例。这个角色包含有选择合适的产品对象的逻辑。通常使用具体类实现。
抽象产品(Abstract Product)角色:声明一类产品的接口。它是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:实现抽象产品角色所定义的接口,定义一个将被相应的具体工厂创建的产品对象。其内部包含了应用程序的业务逻辑。

简单工厂模式:
①抽象基类:类中定义抽象一些方法,用以在子类中实现
②继承自抽象基类的子类:实现基类中的抽象方法
③工厂类:用以实例化对象

只要是可以根据不同的参数生成不同的类实例,那么就符合工厂模式的设计思想。

class MyObject{
  //对象将从工厂返回
}
 
class MyFactory{
public static function factory(){
return new MyObject():
   }
}
 
$instance=MyFactory::factory();

 

//这样子做很方便扩展。我们在直接链接数据库的时候,不是使用代码new Mysql($host,$username,$password,$dbname)的形式
 
//而可以动态生成一个连接数据库的实例。可以是mysql,也可以是连接oracle的。
interface db {
    function connect();
}
interface Factory {
    function createDb();
}
class mysqldb implements db {
    public  function  connect() {
        echo '连上了mysql';
    }
}
class sqlite implements db {
    public  function connect() {
        echo '连上了sqllist';
    }
}
class createMysql implements Factory {
    public function createDb(){
        return new mysqldb();
    }
}
class creareLite implements Factory {
    public function createDb(){
        return new sqlite();
    }
}
 
$fact = new createMysql();
var_dump($fact->createDb()->connect());

 

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() {
        //finish PNG job
    }
    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() {
        //finish jpeg job
    }
    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);
                break;
        }
    }
    if($ret instanceof IImage){
        return $ret;
    }else{
        //...
    }
}
//当使用图像文件名调用 工厂方法时,根据传入的文件类型不同,取得不同对象。
$image = ImageFactory::factory('/path/to/my.jpg');
echo $image->getWidth();

具体应用:

比如一个cms, 你不知道客户用的是什么数据库, 可能mysql, sqlserver, pdo. 每切换一次, 就意味着要生成所选择的数据库的链接对象.

希望的效果是, 传一个mysql, 就可以使用mysql的对象, 传一个pdo, 就可以使用pdo的对象.

$db_object=db_factory::get_instance('pdo');//这里你想换哪个数据库,就填哪个,例如mysql,mysqli,pdo

解决办法:

工厂模式.

对应关系如下:

数据库工厂===>db_factory类

各个数据库链接对象===>在db_factory中生产出来的对象, 而不是生产db_factory类的对象 

 

<?php

/**************db_factory.class.php****************/

class db_factory{

    static private $instance=null;

    private  function __construct(){
    }

    static public function get_instance($db_type='mysql'){

        if(self::$instance==null){

            self::$instance=new self();

        }

        $db_factory=self::$instance;

        return $db_factory->getDbObject($db_type);

    }


    protected function getDbObject($db_type){

        switch($db_type){

            case 'mysql':

                $obj=getMysql::get_instance();

            break;

            case 'mysqli':

                $obj=getMysqli::get_instance();

            break;

            case 'pdo':

                $obj=getPdo::get_instance();

            break;

            default :

                $obj=getMysql::get_instance();

        }

        return $obj;

    }

}



/**************getMysql.class.php****************/

class getMysql{

    static private $instance=null;



    private  function __construct(){

    }

    

    static public function get_instance(){

        if(self::$instance==null){

            self::$instance=new self();

        }

        return self::$instance;

    }

    

    function select(){

        echo 'mysql获取数据';

    }

}



/**************getMysqli.class.php****************/

class getMysqli{

    static private $instance=null;



    private  function __construct(){

    }

    

    static public function get_instance(){

        if(self::$instance==null){

            self::$instance=new self();

        }

        return self::$instance;

    }

    

    function select(){

        echo 'mysqli获取数据';

    }

}



/**************getPdo.class.php****************/

class getPdo{

    static private $instance=null;



    private  function __construct(){

    }

    

    static public function get_instance(){

        if(self::$instance==null){

            self::$instance=new self();

        }

        return self::$instance;

    }

    

    function select(){

        echo 'pdo获取数据';

    }

}


/**************客户端调用****************/

$db_object=db_factory::get_instance('pdo');//这里你想换哪个数据库,就填哪个,例如mysql,mysqli,pdo

$db_object->select();


?>

在需要对象的切换时候可以选择这种模式, 但是对象的切换最好不要超过10, 多了后这种方式的弊端就会显现, 显得累赘了.

这个也不错

http://blog.csdn.net/hguisu/article/details/7505909

 

单例模式

优点:

1. 在内存中只有一个实例, 减少内存开支, 尤其是一个对象需要频繁创建, 销毁的时候. 而且创建销毁的过程又无法优化, 单例模式的优势就非常明显.

2. 由于单例模式只产生一个对象, 所以减少了对系统性能的开销, 当一个对象的产生需要比较多的资源时, 如读取配置或产生其他依赖对象时, 然后用永久驻留内存的方式来解决.

3. 单例模式避免对资源的多重占用, 例如一个写文件的动作, 由于只有一个实例存在于内存中, 可以避免对同一资源文件的的同时写操作. 

4. 单例模式可以在系统设置全局的访问点, 优化和共享资源访问, 例如设计一个单例类, 负责数据所有表的映射处理.

 

参考自:http://lobert.iteye.com/blog/2033957

posted @ 2015-05-15 18:30  derrck  阅读(634)  评论(0编辑  收藏  举报