简单工厂的核心是 switch 或者 if 判断;
但是简单工厂配合抽象工厂的时候;
工厂里面的每个用来实例化产品的方法都需要 switch ;
这就显的重复了;
这时候我们可以使用反射来优化;
多个 interface 或者 abstract 产品父类;
多个实现 interface 或者继承 abstract 的具体产品类;
1个工厂;
工厂类里面有多个方法分别实例化不同的具体产品类;
产品部分跟抽象工厂是一样的;
先创建 User 和 Article 产品 interface ;
User.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithReflection;
/**
* User 产品接口
*
* Interface User
* @package Baijunyao\DesignPatterns\AbstractFactoryWithReflection
*/
interface User
{
/**
* 新增
*
* @return mixed
*/
public function insert();
/**
* 查询
*
* @return mixed
*/
public function select();
}
Article.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithReflection;
/**
* Article 产品接口
*
* Interface Article
* @package Baijunyao\DesignPatterns\AbstractFactoryWithReflection
*/
interface Article
{
/**
* 新增
*
* @return mixed
*/
public function insert();
/**
* 查询
*
* @return mixed
*/
public function select();
}
然后创建对应的 MySQL 产品;
MySQLUser.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithReflection;
/**
* 应用于 MySQL 的 User
*
* Class MySQLUser
* @package Baijunyao\DesignPatterns\AbstractFactoryWithReflection
*/
class MySQLUser implements User
{
/**
* 新增
*/
public function insert()
{
echo '向 MySQL 数据库中插入 User';
}
/**
* 查询
*/
public function select()
{
echo '从 MySQL 数据库中查询 User';
}
}
MySQLArticle.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithReflection;
/**
* 应用于 MySQL 的 Article
*
* Class MySQLArticle
* @package Baijunyao\DesignPatterns\AbstractFactoryWithReflection
*/
class MySQLArticle implements Article
{
/**
* 新增
*/
public function insert()
{
echo '向 MySQL 数据库中插入 Article';
}
/**
* 查询
*/
public function select()
{
echo '从 MySQL 数据库中查询 Article';
}
}
然后创建对应的 SQLite 产品;
SQLiteUser.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithReflection;
/**
* 适用于 SQLite 的 User
*
* Class SQLiteUser
* @package Baijunyao\DesignPatterns\AbstractFactoryWithReflection
*/
class SQLiteUser implements User
{
/**
* 新增
*/
public function insert()
{
echo '向SQLite数据库中插入 User';
}
/**
* 查询
*/
public function select()
{
echo '从SQLite数据库中查询 User';
}
}
SQLiteArticle.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithReflection;
/**
* 适用于 SQLite 的 Article
*
* Class SQLiteArticle
* @package Baijunyao\DesignPatterns\AbstractFactoryWithReflection
*/
class SQLiteArticle implements Article
{
/**
* 新增
*
* @return mixed|void
*/
public function insert()
{
echo '向 SQLite 数据库中插入 Article';
}
/**
* 查询
*
* @return mixed|void
*/
public function select()
{
echo '从 SQLite 数据库中查询 Article';
}
}
产品部分没有什么变化;
配置项也一样;
config.php
<?php
return [
'driver' => 'MySQL'
];
核心就是反射部分;
Factory.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithReflection;
use ReflectionClass;
use ReflectionException;
class Factory
{
/**
* 数据库
*
* @var string
*/
public $db = 'MySQL';
/**
* 产品类的命名空间
*
* @var string
*/
public $namespace = 'Baijunyao\DesignPatterns\AbstractFactoryWithReflection\\';
/**
* Factory constructor.
*/
public function __construct()
{
/**
* 从配置项中获取 driver
*/
$config = include 'config.php';
$this->db = $config['driver'];
}
/**
* 创建 User 产品
*
* @return MySQLUser|SQLiteUser
*/
public function createUser()
{
$className = $this->namespace . $this->db . 'User';
try {
$class = new ReflectionClass($className);
$user = $class->newInstance();
} catch (ReflectionException $Exception) {
throw new \InvalidArgumentException('暂不支持的数据库类型');
}
return $user;
}
/**
* 创建 Article 产品
*
* @return MySQLArticle|SQLiteArticle
*/
public function createArticle()
{
$className = $this->namespace . $this->db . 'Article';
try {
$class = new ReflectionClass($className);
$article = $class->newInstance();
} catch (ReflectionException $Exception) {
throw new \InvalidArgumentException('暂不支持的数据库类型');
}
return $article;
}
}
运行;
index.php
<?php
namespace Baijunyao\DesignPatterns\AbstractFactoryWithReflection;
require __DIR__.'/../vendor/autoload.php';
/**
* 客户端
*
* Class Client
* @package Baijunyao\DesignPatterns\AbstractFactoryWithReflection
*/
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();
当我们需要支持更多的数据库的时候;
比如说 PostgreSQL ;
我们只需要新建 PostgreSQLUser 和 PostgreSQLArticle ;
这就符合开闭原则了;
可以方便的扩展且不需要修改 createUser 方法;
over;
工厂相关的设计模式终于告一段落;
github示例:https://github.com/baijunyao/design-patterns/tree/master/AbstractFactoryWithReflection
本文为白俊遥原创文章,转载无需和我联系,但请注明来自白俊遥博客https://baijunyao.com 欢迎捐赠赞赏加入组织创建QQ群及捐赠渠道
:白哥讲的真是乱八七糟啊
2024-02-23 16:33:26 回复
孤城浪子 :这里的类都没有构造函数所以直接就new了,如果有构造函数是不是还应该加个依赖注入的功能呢。
2018-09-20 18:38:18 回复
Summer :很好
2018-08-28 09:43:56 回复
时光机 :很好
2018-08-18 02:46:44 回复
for_bug_Do_first :&lgt;script&rgt;alert(123123)&lgt;script/&rgt;
2018-08-17 18:10:43 回复
for_bug_Do_first :alert('11111')
2018-08-17 18:09:27 回复
最新评论