抽象工厂模式中每增加一类产品都要改动全部的工厂;
这个工厂就是我们痛苦的源泉了;
这时候可以使用简单工厂来优化抽象工厂;
多个 interface 或者 abstract 产品父类;
多个实现 interface 或者继承 abstract 的具体产品类;
1个工厂;
工厂类里面有多个方法分别实例化不同的具体产品类;
产品部分跟抽象工厂是一样的;
先创建 User 和 Article 产品 interface ;
User.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
/**
* User 产品接口
*
* Interface User
* @package Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory
*/
interface User
{
/**
* 新增
*
* @return mixed
*/
public function insert();
/**
* 查询
*
* @return mixed
*/
public function select();
}
Article.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
/**
* Article 产品接口
*
* Interface Article
* @package Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory
*/
interface Article
{
/**
* 新增
*
* @return mixed
*/
public function insert();
/**
* 查询
*
* @return mixed
*/
public function select();
}
然后创建对应的 MySQL 产品;
MySQLUser.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
/**
* 应用于 MySQL 的 User
*
* Class MySQLUser
* @package Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory
*/
class MySQLUser implements User
{
/**
* 新增
*/
public function insert()
{
echo '向 MySQL 数据库中插入 User';
}
/**
* 查询
*/
public function select()
{
echo '从 MySQL 数据库中查询 User';
}
}
MySQLArticle.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
/**
* 应用于 MySQL 的 Article
*
* Class MySQLArticle
* @package Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory
*/
class MySQLArticle implements Article
{
/**
* 新增
*/
public function insert()
{
echo '向 MySQL 数据库中插入 Article';
}
/**
* 查询
*/
public function select()
{
echo '从 MySQL 数据库中查询 Article';
}
}
然后创建对应的 SQLite 产品;
SQLiteUser.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
/**
* 适用于 SQLite 的 User
*
* Class SQLiteUser
* @package Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory
*/
class SQLiteUser implements User
{
/**
* 新增
*/
public function insert()
{
echo '向SQLite数据库中插入 User';
}
/**
* 查询
*/
public function select()
{
echo '从SQLite数据库中查询 User';
}
}
SQLiteArticle.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
/**
* 适用于 SQLite 的 Article
*
* Class SQLiteArticle
* @package Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory
*/
class SQLiteArticle implements Article
{
/**
* 新增
*
* @return mixed|void
*/
public function insert()
{
echo '向 SQLite 数据库中插入 Article';
}
/**
* 查询
*
* @return mixed|void
*/
public function select()
{
echo '从 SQLite 数据库中查询 Article';
}
}
产品部分没有什么变化;
那工厂就是优化的关键了;
Factory.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
class Factory
{
public $db = 'MySQL';
/**
* 创建 User 产品
*
* @return MySQLUser|SQLiteUser
*/
public function createUser()
{
switch ($this->db) {
case 'MySQL':
$user = new MySQLUser();
break;
case 'SQLite':
$user = new SQLiteUser();
break;
default:
throw new \InvalidArgumentException('暂不支持的数据库类型');
}
return $user;
}
/**
* 创建 Article 产品
*
* @return MySQLArticle|SQLiteArticle
*/
public function createArticle()
{
switch ($this->db) {
case 'MySQL':
$article = new MySQLArticle();
break;
case 'SQLite':
$article = new SQLiteArticle();
break;
default:
throw new \InvalidArgumentException('暂不支持的数据库类型');
}
return $article;
}
}
运行;
index.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
require __DIR__.'/../vendor/autoload.php';
/**
* 客户端
*
* Class Client
* @package Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory
*/
class Client
{
/**
* 运行
*/
public function run()
{
$factory = new Factory();
// 创建 user
$user = $factory->createUser();
$user->insert();
echo '<br>';
$user->select();
echo '<hr>';
// 创建 article
$article = $factory->createArticle();
$article->insert();
echo '<br>';
$article->select();
}
}
$client = new Client();
$client->run();
不过 Factory 中把 db 属性固定为 MySQL 了;
想换数据库类型还需要手动修改 db ;
我们还可以写个配置文件;
从配置文件中读取;
这样就不用改动 Factory 文件了;
config.php
<?php
return [
'driver' => 'MySQL'
];
Factory.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithSimpleFactory;
class Factory
{
public $db = 'MySQL';
/**
* Factory constructor.
*/
public function __construct()
{
/**
* 从配置项中获取 driver
*/
$config = include 'config.php';
$this->db = $config['driver'];
}
/**
* 创建 User 产品
*
* @return MySQLUser|SQLiteUser
*/
public function createUser()
{
switch ($this->db) {
case 'MySQL':
$user = new MySQLUser();
break;
case 'SQLite':
$user = new SQLiteUser();
break;
default:
throw new \InvalidArgumentException('暂不支持的数据库类型');
}
return $user;
}
/**
* 创建 Article 产品
*
* @return MySQLArticle|SQLiteArticle
*/
public function createArticle()
{
switch ($this->db) {
case 'MySQL':
$article = new MySQLArticle();
break;
case 'SQLite':
$article = new SQLiteArticle();
break;
default:
throw new \InvalidArgumentException('暂不支持的数据库类型');
}
return $article;
}
}
虽然有了简单工厂可以少建一堆工厂了;
但是这里面的多个 switch 明显是有点重复的;
这呼吸起来还是有点痛;
下篇文章我们用反射优化抽象工厂进一步减轻这种痛;
github示例:https://github.com/baijunyao/design-patterns/tree/master/AbstractFactoryWithSimpleFactory
本文为白俊遥原创文章,转载无需和我联系,但请注明来自白俊遥博客https://baijunyao.com 欢迎捐赠赞赏加入组织创建QQ群及捐赠渠道
最新评论