【工厂模式】设计模式之工厂模式【原创】


摘要:主要是参考列旭松、陈文著的《PHP核心技术与最佳实践》的2.1节。


1.1 简介

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。工厂模式(Factory)允许你在代码执行时实例化对象。之所以被称为工厂模式是因为它只负责‘生产’对象。以数据库为例,工厂需要的是根据不同的参数,生产不同的实例化对象。最简单的工厂模式就是根据传入的类型名实例化对象,比如传入Mysql,就调用Mysql的类并实例化,比如传入SQLite,则调用SQLite的类并实例化,甚至可以处理TXT、EXCEL等‘类数据库’。工厂类就是这样的类,只负责生产对象,而不负责对象的具体内容。
工厂方法让具体的对象解脱了出来,使其并不再依赖具体的类,而是抽象。

1.2 优点

工厂模式的优点在于创建对象上。 建立一个工厂(一个函数或一个类方法)来制造新的对象,它的任务就是把对象的创建过程都封装起来, 创建对象不是使用new的形式了。而是定义一个方法,用于创建对象实例。
通俗的说,以前创建一个对象要使用new,现在把这个过程封装起来了。
假设不使用工厂模式:那么很多地方调用类a,代码就会这样子创建一个实例:new a(),假设某天需要把a类的名称修改,意味着很多调用的代码都要修改。

1.3 简单的工厂模式例子

1
<?php
2
    interface abstracted
3
    {
4
        public function realCreate();
5
    }
6
7
    //女人类
8
    class Woman
9
    {
10
        public function action()
11
        {
12
            echo '这是女人';
13
        }
14
    }
15
16
    //男人类
17
    class Man
18
    {
19
        public function action()
20
        {
21
            echo '这是男人';
22
        }
23
    }
24
25
    //创建女人
26
    class WomanCreator implements abstracted 
27
    {
28
        public $chromosome;//染色体
29
        public function realCreate(){
30
            if ($this->chromosome == "xx") {
31
                return new Woman();
32
            }
33
        }
34
    }
35
36
    //创建男人
37
    class ManCreator implements abstracted 
38
    {
39
        public $chromosome;
40
        public function realCreate()
41
        {
42
            if ($this->chromosome == "xy" || $this->chromosome == "xyy") {
43
                return new Man();
44
            }
45
        }
46
    }
47
48
    //人类工厂
49
    class PersonFactory
50
    {
51
        public function create($what){
52
            $create = $what."Creator";
53
            return $create = new $create();
54
        }
55
    }
56
57
    $create = new PersonFactory();
58
    $instance = $create->create('Woman');
59
    $instance->chromosome = "xx";
60
    $instance->realCreate()->action();

1.4 数据库适配器

使用工厂模式定义数据库适配器,根据不同的数据库参数实例化不同的数据库类。

定义一个数据库适配器接口,规定一些通用的方法:
2_Drivers\Db_Adapter.php:
<?php
/**
 * Db的适配器
 */

interface Db_Adapter
{
    /**
     * 数据库连接
     * @param array $config 数据库配置
     * @return resource
     */
    public function connect($config);

    /**
     * 执行数据库查询
     * @param string $query 数据库查询SQL字符串
     * @return resource
     */
    public function query($query);
}



定义一个Mysql数据库的操作类(简化版),实现了数据库适配器接口:
2_Drivers\Db_Adapter_Mysqli.php:
1
<?php
2
/**
3
 * 定义MySql数据库的操作类
4
 */
5
6
require_once 'Db_Adapter.php';
7
8
class Db_Adapter_Mysqli implements Db_Adapter
9
{
10
    // 数据库连接字符串标示
11
    private $_dbLink;
12
13
    /**
14
     * 数据库连接函数
15
     * @param array $config 数据库配置
16
     * @return mysqli
17
     */
18
    public function connect($config)
19
    {
20
        $this->_dbLink = @mysqli_connect($config['host'] . (empty($config['port']) ? '' : ':' . $config['port']), $config['user'], $config['password']);
21
        if ($this->_dbLink) {
22
            if (@mysqli_select_db($this->_dbLink, $config['database'])) {
23
                if (isset($config['charset'])) {
24
                    mysqli_query($this->_dbLink, "SET NAMES '{$config['charset']}'");
25
                }
26
                return $this->_dbLink;
27
            }
28
        }
29
30
        // 数据库异常
31
        throw new mysqli_sql_exception(@mysqli_error($this->_dbLink));
32
    }
33
34
    /**
35
     * 执行数据库查询
36
     * @param string $query 数据库查询SQL字符串
37
     * @return bool|mysqli_result
38
     */
39
    public function query($query)
40
    {
41
        $handle = $this->_dbLink;
42
        $resource = @mysqli_query($handle, $query);
43
        if ($resource) {
44
            return $resource;
45
        } else {
46
            return false;
47
        }
48
    }
49
}
50

接下来是SQLite数据库的操作类(简化版),同样 实现了数据库适配器接口:
2_Drivers\Db_Adapter_Sqlite.php:
<?php
/**
 * 定义SQLite数据库的操作类
 */

require_once 'Db_Adapter.php';

class Db_Adapter_Sqlite implements Db_Adapter
{
    // 数据库连接字符串标示
    private $_dbLink;

    /**
     * 数据库连接函数
     * @param array $config 数据库配置
     * @return resource
     * @throws Exception
     */
    public function connect($config)
    {
        $this->_dbLink = sqlite_open($config['file'], 0666, $error);
        if ($this->_dbLink){
            return $this->_dbLink;
        }

        // 数据库异常
        throw new Exception($error);
    }

    /**
     * 执行数据库查询
     * @param string $query 数据库查询SQL字符串
     * @return bool|resource
     */
    public function query($query)
    {
        $handle = $this->_dbLink;
        $resource = @sqlite_query($query, $handle);
        if ($resource) {
            return $resource;
        } else {
            return false;
        }
    }
}

定义一个工厂类,根据不同的参数生成不同的数据库类,并实现简单的查询:
2_4_sql_factory.php:
1
<?php
2
/**
3
 * 定义一个工厂类,可以根据参数的不同生成不同的数据库类
4
 */
5
6
class SqlFactory
7
{
8
    public static function factory($type)
9
    {
10
        if (include_once '2_Drivers/Db_Adapter_' . $type. '.php') {
11
            $classname = 'Db_Adapter_' . $type;
12
            return new $classname;
13
        } else {
14
            throw new Exception('Driver not found');
15
        }
16
    }
17
}
18
19
$db = SqlFactory::factory('Mysqli');
20
$config = [
21
    'host' => 'localhost',
22
    'user' => 'root',
23
    'password' => '123456',
24
    'database' => 'test_laravel',
25
];
26
$db->connect($config);
27
$res = $db->query('SELECT * FROM articles');
28
while ($row = mysqli_fetch_row($res)) {
29
    var_dump($row);
30
}
31

注意:要调用时,可以这样写:
$db = sqlFactory:factory('Mysqli');
$db = sqlFactory:factory('Sqlite');








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值