工厂方法模式

假设要实现一个功能,要封装访问数据库的操作。
1. 不实用设计模式的情况:

/**
 *文件列表
 *|
 *|--Database.php 数据库封装类
 *|--main.php 使用程序(客户端)
 */

/**
 * Database.php 数据库封装
 */
class Database{
    public $connect = null;
    function select(){
        //...
    }
    function insert(){
        //...
    }
    function update(){
        //...
    }

    function delete(){
        //...
    }
}

/**
 * main.php
 */
$db = new Database();
$db->select();

//缺点:耦合严重,不好扩展

2. 简单工厂

/**
 *文件列表
 *|--drivers 数据库连接封装
     |-- BaseDrivers.php 产品超类
     |-- Mysql.php 具体的产品
     |-- TiDb.php 另一个具体的产品
 *|--DbFactory.php 数据库工厂
 *|--main.php 使用程序(客户端)
 */

/**
 * DbFactory.php 数据库工厂(简单工厂,产品是指定类型的数据库操作具柄)
 */
class DbFactory
{
    public static function getDatabase($name):Database
    {
        if($name == "mysql"){
            return new Mysql();
        }else if($name = "tidb"){
            return new TiDb();
        }

        throw new \Exception("driver not find:".$name);
    }
}

/**
 * BaseDrivers.php 数据库驱动基础类(简单工厂模式中的产品的超类,定义产品接口)
 */
abstract class BaseDrivers
{
    public $connect = null;
    abstract function select();
    abstract function insert();
    abstract function update();
    abstract function delete();
}


/**
 * Mysql.php mysql 数据库驱动类(具体的产品)
 */
class Mysql extends BaseDrivers
{

    function select()
    {
        // TODO: Implement select() method.
    }

    function insert()
    {
        // TODO: Implement insert() method.
    }

    function update()
    {
        // TODO: Implement update() method.
    }

    function delete()
    {
        // TODO: Implement delete() method.
    }
}


/**
 * TiDb.php tidb数据库驱动类(另一种具体的产品)
 */
class TiDb extends BaseDrivers
{

    function select()
    {
        // TODO: Implement select() method.
    }

    function insert()
    {
        // TODO: Implement insert() method.
    }

    function update()
    {
        // TODO: Implement update() method.
    }

    function delete()
    {
        // TODO: Implement delete() method.
    }
}


/**
 * main.php
 */
$database = DbFactory::getDatabase('mysql');//获取mysql的数据库操作
$database->select();

//优点:不说了,自行百度
//缺点:如果在添加其他的数据库类型操作,必须得修改DbFactory.php,增加 if...else... ,然后才能在main中获取新的数据库操作句柄

3. 工厂方法模式

/**
 *文件列表
 *|--drivers 数据库连接封装
     |-- BaseDrivers.php 产品超类
     |-- Mysql.php 具体的产品
     |-- TiDb.php 另一个具体的产品
 *|--factories.php 工厂封装
 *   |-- BaseFactory.php 工厂超类
 *   |-- MysqlFactory.php 具体工厂(只生产mysql产品的工厂)
 *   |-- TiDbFactory.php 另一个具体的工厂(只生产TiDb产品的工厂)
 *|--main.php 使用程序(客户端)
 */

/**
 * BaseFactory.php 工厂超类
 */
interface  BaseFactory
{
    function getDb();
}


/**
 * MysqlFactory.php mysql工厂
 */
class MysqlFactory implements BaseFactory
{
    function getDb()
    {
        return new Mysql();
    }
}


/**
 * TiDbFactory.php TiDb工厂
 */
class TiDbFactory implements BaseFactory
{
    function getDb()
    {
        return new TiDb();
    }
}

/**
 * BaseDrivers.php 数据库驱动基础类
 */
abstract class BaseDrivers
{
    public $connect = null;
    abstract function select();
    abstract function insert();
    abstract function update();
    abstract function delete();
}


/**
 * Mysql.php mysql 数据库驱动类
 */
class Mysql extends BaseDrivers
{

    function select()
    {
        // TODO: Implement select() method.
    }

    function insert()
    {
        // TODO: Implement insert() method.
    }

    function update()
    {
        // TODO: Implement update() method.
    }

    function delete()
    {
        // TODO: Implement delete() method.
    }
}


/**
 * TiDb.php tidb数据库驱动类
 */
class TiDb extends BaseDrivers
{

    function select()
    {
        // TODO: Implement select() method.
    }

    function insert()
    {
        // TODO: Implement insert() method.
    }

    function update()
    {
        // TODO: Implement update() method.
    }

    function delete()
    {
        // TODO: Implement delete() method.
    }
}


/**
 * main.php
 */
$database = MysqlFactory::getDb();
$database->select();

//优点:新增数据库类型时,不用在修改框架部分代码(没有了Factory.php,不用在依赖这个类了)。只需要新添加一个对应的工厂,然后新增加一个数据库driver(产品),就可以直接在客户端(main.php)使用了,完全不影响其他的已经完成的功能。
此条目发表在设计模式分类目录。将固定链接加入收藏夹。