10-抽象工厂模式
目录
简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?
就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
代码示例
<?php
namespace DesignPattern;
/**
* Description of AbstractFactoryDemo
* 抽象工厂
* @author jm
*/
class AbstractFactoryDemo
{
/**
* 入口方法
*/
public static function main(){
$channelData = [
"name"=>"huawei",
"appid"=>"xxxx"
];
//方式1
$channelObj = ChannelFactory::createChannel($channelData);
$userModule = $channelObj->createUser();
$userModule->login([]);
$payModule = $channelObj->createPay();
$payModule->order();
$payModule->payCallback();
// //方式2
// $channelObj = new Channel($channelData);
// $userModule = ModuleFactory::createUserModule($channelObj);
// $userModule->login([]);
// $payModule = ModuleFactory::createPayModule($channelObj);
// $payModule->order();
// $payModule->payCallback();
}
}
/**
* 用户模块接口
*/
interface IUserModule{
public function login($data);
}
/**
* 支付模块接口
*/
interface IPayModule{
public function order();
public function payCallback();
}
//模块 父类
class Module{
protected $channeObj = null;
public function __construct($channelObj)
{
$this->channeObj = $channelObj;
}
}
/**
* 华为渠道用户模块
*/
class HuaweiUser extends Module implements IUserModule
{
public function login($data)
{
echo "huawei Login success.".PHP_EOL;
return "";
}
}
/**
* 华为渠道支付模块
*/
class HuaweiPay extends Module implements IPayModule
{
public function order()
{
echo "huawei generate order.".PHP_EOL;
return true;
}
public function payCallback(){
echo "huawei pay callback success.".PHP_EOL;
return true;
}
}
/**
* 小米渠道用户模块
*/
class XiaomiUser extends Module implements IUserModule
{
public function login($data)
{
echo "xiaomi Login success.".PHP_EOL;
return "";
}
}
/**
* 小米渠道支付模块
*/
class XiaomiPay extends Module implements IPayModule
{
public function order()
{
echo "xiaomi generate order.".PHP_EOL;
return true;
}
public function payCallback(){
echo "xiaomi pay callback success.".PHP_EOL;
return true;
}
}
//
///**
// * 应用宝渠道用户模块
// */
//class YingyongbaoUser extends Module implements IUserModule
//{
//
// public function login($data)
// {
// echo "应用宝 Login success.".PHP_EOL;
// return "";
// }
//}
///**
// * 应用宝渠道支付模块
// */
//class YingyongbaoPay extends Module implements IPayModule
//{
//
// public function order()
// {
// echo "应用宝 generate order.".PHP_EOL;
//
// return true;
// }
//
// public function payCallback(){
// echo "应用宝 pay callback success.".PHP_EOL;
// return true;
// }
//}
//渠道 父类
class Channel{
private $_channelData = [];
private $_channeName = 'xiaomi';
public function __construct($channelData)
{
$this->_channelData = $channelData;
$this->_channeName = $channelData['name'];
}
public function getChanneData(){
return $this->_channelData;
}
public function getChannelName(){
return $this->_channeName;
}
}
//渠道接口 规约
interface IChannel{
public function createUser();
public function createPay();
}
//华为渠道
class Huawei extends Channel implements IChannel{
public function createUser(){
return new HuaweiUser($this->getChanneData());
}
public function createPay(){
return new HuaweiPay($this->getChanneData());
}
}
//小米渠道
class Xiaomi extends Channel implements IChannel{
public function createUser(){
return new XiaomiUser($this->getChanneData());
}
public function createPay(){
return new XiaomiPay($this->getChanneData());
}
}
////新增 应用宝渠道
//class Yingyongbao extends Channel implements IChannel{
// public function createUser(){
// return new YingyongbaoUser($this->getChanneData());
// }
// public function createPay(){
// return new YingyongbaoPay($this->getChanneData());
// }
//}
//渠道工厂
class ChannelFactory{
public static function createChannel($channelData){
$className = "\\DesignPattern\\".ucfirst($channelData['name']);
return new $className($channelData);
}
}
////方式2
//class ModuleFactory{
// public static function createUserModule($channelObj){
// $className = "\\DesignPattern\\".ucfirst($channelObj->getChannelName())."User";
// return new $className($channelObj);
// }
// public static function createPayModule($channelObj){
// $className = "\\DesignPattern\\".ucfirst($channelObj->getChannelName())."Pay";
// return new $className($channelObj);
// }
//}
AbstractFactoryDemo::main();
输出:
huawei Login success.
huawei generate order.
huawei pay callback success.
注:抽象工厂经常用在数据库模型上,有多种数据库(Oracle、mysql、sqlserver、MongoDB等),数据库有多种操作(连接、curd、表操作等)
工厂方法比对
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例,也就是创建的是一个产品线下的多个产品。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
工厂方法创建 “一种” 产品,他的着重点在于"怎么创建”,也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随。
抽象工厂需要创建一些列产品,着重点在于"创建哪些"产品上,也就是说,如果你开发,你的主要任务是划分不同差异的产品线,并且尽量保持每条产品线接口一致,从而可以从同一个抽象工厂继承。
小结
抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体类。
抽象工厂模式的好处便是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只是需要改变具体工厂即可使用不同的产品配置。它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
本文部分收藏来自互联网,仅用于学习研究,著作权归原作者所有,如有侵权请联系删除
markdown 9ong@TsingChan