之前我们说过简单工厂模式和工厂模式。都是针对单一支付类来写。但在开发过程我们常会做一个促销活动,而且有些促销是针对支付方式的。比如公司和招商银行签订了战略合作,招商银行会给我们引流,公司给用招商银行支付的用户赠送礼品、优惠券或直接打折。这样就会用两个维度:支付方式和促销。那这又如何处理呢?
现在我们通过这个例子来讲解抽象工厂模式:
首先、需要一个支付抽象类Payment,在这个基础上可以扩展支付宝支付、微信支付、招商银行支付等。
其次、需要一个促销类型的抽象类Promotion, 在这个基础上可以扩展送优惠券、送赠品、直接打折。
最后、由于促销和支付就可以相互独立,促销不仅可以针对支付方式,还可以在新用户注册、节假日促销活动用。针对该案例我们需要写一个抽象工厂类将支付方式与促销方式关联起来。
现在针对招商银行支付要直接打折,来看具体代码如何实现:
1、在工产模式的基础上保持代码不变。
2、新加一个Promotion接口及实现Promotion的具体促销类。
Promotion接口:
/**
* file name: Promote.php
* user : 良子
* date : 2020-12-30
*/
namespace libs\abstract_factory;
interface Promotion
{
public function setPromote(array $input);
}
DiscountPromotion折扣类:
/**
* file name: DiscountPromotion.php
* user : 良子
* date : 2020-12-30
*/
namespace libs\abstract_factory;
class DiscountPromotion implements Promotion
{
public function setPromote(array $input)
{
// TODO: Implement set_promote() method.
echo '<br/>进行打扣处理……<br/>';
}
}
GiveCouponPromotion赠送优惠券类:
/**
* file name: GiveCouponPromotion.php
* user : 良子
* date : 2020-12-30
*/
namespace libs\abstract_factory;
class GiveCouponPromotion implements Promotion
{
public function setPromote(array $input)
{
// TODO: Implement set_promote() method.
echo '<br/>赠送优惠券处理……<br/>';
}
}
GiveGiftPromotion赠送礼品类:
/**
* file name: GiveGiftPromotion.php
* user : 良子
* date : 2020-12-30
*/
namespace libs\abstract_factory;
class GiveGiftPromotion implements Promotion
{
public function setPromote(array $input)
{
// TODO: Implement set_promote() method.
echo '<br/>赠送赠品处理……<br/>';
}
}
3、加一个支付促销抽象接口PayPromotionFactory
/**
* file name: PayPromotionFactory.php
* user : 良子
* date : 2020-12-30
*/
namespace libs\abstract_factory;
interface PayPromotionFactory
{
public function getPayment();
public function getPromotion();
}
加一个针对招行支付的折扣促销工厂类ZhanghangDiscountFactory
/**
* file name: ZhanghangDiscountFactory.php
* user : 良子
* date : 2020-12-30
*/
namespace libs\abstract_factory;
class ZhanghangDiscountFactory implements PayPromotionFactory
{
public function getPayment()
{
return new Zhaoshangpay();
}
public function getPromotion()
{
return new DiscountPromotion();
}
}
之后如果有赠送优惠券的可加一个针对招行支付的赠送优惠券促销工厂类ZhanghangGiveCouponFactory
/**
* file name: ZhanghangDiscountFactory.php
* user : 良子
* date : 2020-12-30
*/
namespace libs\abstract_factory;
class ZhanghangGiveCouponFactory implements PayPromotionFactory
{
public function getPayment()
{
return new Zhaoshangpay();
}
public function getPromotion()
{
return new GiveCouponPromotion();
}
}
这时小王在处理订单逻辑时只要稍修改即可实现针对招行的折扣促销
/**
* file name: abstract_factory.php
* user : 良子
* date : 2020-12-30
*/
require_once ('./libs/loader/Loader.php');
spl_autoload_register('\\libs\\loader\\Loader::autoload');
use libs\abstract_factory\AlipayFactory;
use libs\abstract_factory\WechatpayFactory;
use libs\abstract_factory\ZhanghangDiscountFactory;
$input = [
'order_no' => '订单号',
'total' => '10',
'payment' => 'Zhangshangpay'
];
switch ($input['payment']) {
case 'Alipay':
$factory = new AlipayFactory();
break;
case 'Wechatpay':
$factory = new WechatpayFactory();
break;
case 'Zhangshangpay':
$factory = new ZhanghangDiscountFactory();
break;
default :
exit('不支持此支付方式');
}
if ($input['payment'] == 'Zhangshangpay') {
$promotion = $factory->getPromotion();
$promotion->setPromote($input);
}
$pay = $factory->getPayment();
$pay->goPay($input);
没有招行促销的代码是:
/**
* file name: index.php
* user : 小王
* date : 2020-12-28
*/
require_once ('./libs/loader/Loader.php');
spl_autoload_register('\\libs\\loader\\Loader::autoload');
use libs\factory\AlipayFactory;
use libs\factory\WechatpayFactory;
$input = [
'order_no' => '订单号',
'total' => '10',
'payment' => 'Paypal'
];
switch ($input['payment']) {
case 'Alipay':
$payment = new AlipayFactory();
break;
case 'Wechatpay':
$payment = new WechatpayFactory();
break;
default :
exit('不支持此支付方式');
}
$pay = $payment->getPayment();
$pay->goPay($input);
对比可以发现此时小王只增加了一个case分支,当为招行支付时实现化ZhanghangDiscountFactory, 然后执行setPromote和goPay,小王在整个开发过程中即不需要知道具体的Payment类和Promotion类,他只需要知道Payment的类有goPay方法和Promotion的类有setPromotion即可。如此一来我们代码的扩展实现了高聚合低耦合。
Promotion相关的Payment相关的是相互独立,通过抽象工厂将其关联。
代码结构图:
抽象工厂模式定义(Abstract Factory Pattern)
提供一个创建一系列相关或者相互依赖对象的接口,而无需知道他们的具体类,抽象工厂模式也称Kit模式,它属于类创建型模式。
在抽象工厂模式中,每个具体工厂都提供了多个工厂方法用于创建多种不同类型的具体对象,这些被创建的对象就构成一个族。
抽象工厂模式包含的角色
-
抽象工厂:声明一组用于创建一个族产品的方法,每个方法对应一种对象;在抽象工厂中声明了多个工厂方法, 用于创建不同类型的对象, 抽象工厂可以是接口, 也可以是抽象类或者具体类,具体实现可参考上例中的PayPromotionFactory;
-
具体工厂:具体工厂实现了抽象工厂,每个工厂方法返回一个具体对象,一个具体工厂所创建的具体对象构成一个族。具体实现可参考上例中的ZhanghangDiscountFactory;
-
抽象类接口:提供一组所有类都具有的业务方法。如Payment和Promotion接口;
-
具体类:该角色继承抽象类,主要用于实现抽象类中声明的抽象方法,完成不同等级结构,不同族的业务方法的具体实现。像Zhanghangpay和DiscountPromotion。
关注快乐程序员公众号,每日分享一点小知识。爱编程,爱生活!