从上一篇文章中发现简单工厂模式里有一些瑕疵,虽然PHP不需要重新编译但小张之后每次新加一个支付方式都要告知负责人去修改PayFactory。实例化对象的逻辑全部封装在一个工厂类里,每次需求变化都要单独修改工厂类(违反了开闭原则),而且出了异常可能所有相关功能类都正常工作。
简单解释一下开闭原则:开闭原则规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要代码审查,单元测试以及诸如此类的用以确保产品使用质量的过程。遵循这种原则的代码在扩展时并不发生改变,因此无需上述的过程。如果改了工厂类似乎还重新审查,测试……
对于一个技术负责人更多的是从事系统架构、技术攻关及制定标准,所以从简单工厂模式中衍生从工厂模式。
此时负责人制定两个接口Payment和PayFactory
/**
* file name: PayFactory.php
* user : 良子
* date : 2020-12-28
*/
namespace libs\pay;
interface Payment {
/**
* *@function 订单支付
* @param array $input 支付订单信息
* @return array [
* 'status'=> 1 , //状态 1:成功, 2:失败
* 'message' => '支付成功' //结果说明
* ]
*/
public function pay(array $input);
/**
* @function 用户支付后第三方支付的回调验证
* @param array $input
* @return array [
* 'status'=> 1 , //状态 1:成功, 2:失败
* 'message' => '支付成功' //结果说明
* ]
*/
public function notify(array $input);
}
PayFactory接口
/**
* file name: PayFactory.php
* user : 良子
* date : 2020-12-28
*/
namespace libs\pay;
interface PayFactory
{
//由具体工厂去实现
public function getPayment();
}
小张的工作实现支付宝支付类(Alipay)和支付宝工厂类(AliFactory)的开发
/**
* file name: Alipay.php
* user : 小张
* date : 2020-12-28
*/
namespace libs\pay;
class Alipay implements Payment
{
public function pay (array $input)
{
// TODO: Implement pay() method.
echo '
正在与支付宝进行对接……
';
echo '对接成功……
';
return ['status'=>1, 'message'=>'支付宝支付成功'];
}
public function notify (array $input)
{
// TODO: Implement notify() method.
echo '
正在与支付宝进行对接……
';
echo '校验成功……
';
return ['status'=>1, 'message'=>'支付宝回调校验成功'];
}
}
/**
* file name: AliFactory.php
* user : 小张
* date : 2020-12-28
*/
namespace libs\pay;
class AliFactory implements PayFactory
{
public function getPayment ()
{
// TODO: Implement getPayment() method.
return new Alipay();
}
}
小李的工作实现微信支付类(Wechat)和支付宝工厂类(WechatFactory)的开发
/**
* file name: Wechatpay.php
* user : 小李
* date : 2020-12-27
*/
namespace libs\pay;
class Wechatpay implements Payment
{
public function pay (array $input)
{
// TODO: Implement pay() method.
echo '
正在与微信进行对接……
';
echo '对接成功……
';
return ['status'=>1, 'message'=>'微信支付成功'];
}
public function notify (array $input)
{
// TODO: Implement notify() method.
echo '
正在与微信进行对接……
';
echo '校验成功……
';
return ['status'=>1, 'message'=>'微信回调校验成功'];
}
}
/**
* file name: WechatFactory.php
* user : 小李
* date : 2020-12-28
*/
namespace libs\pay;
class WechatFactory implements PayFactory
{
public function getPayment ()
{
// TODO: Implement getPayment() method.
return new Wechatpay();
}
}
小王的工作是实现订单的业务逻辑,并根据用户的选择调用不同的支付方式:
/**
* file name: index.php
* user : 小王
* date : 2020-12-28
*/
require_once ('./libs/loader/Loader.php');
spl_autoload_register('\\libs\\loader\\Loader::autoload');
use libs\pay\PayFactory;
echo '订单处理中……
';
//订单信息
$input = [
'order_no' => '20000001', //订单号
'total' => '120', //金额
'payment' => 'Wechatpay'
//……
];
switch ($input['payment']) {
case 'Alipay': //支付宝支付
$payFactory = new \libs\pay\AliFactory();
break;
case 'Wechatpay' : //微信支付
$payFactory = new \libs\pay\WechatFactory();
break;
default :
echo '请选择正确的支付方式';
exit();
}
$payment = $payFactory->getPayment();
$payResult = $payment->pay($input);
var_dump($payResult);
整个例子的文件结构图:
如果之后小张要新加paypal只需要创建Paypalpay去实现Payment,创建PaypalFactory去实现PayFactory即可,然后告知小王即可。至于之前的支付宝、微信和工厂类就可以完全不受影响,就不需要对这几块进行审查和测试。
工厂模式包含的角色
抽象工厂:工厂模式的核心,提供一个创建对象的接口,任何需要创建对象的具体工厂都要实现这个接口。
具体工厂:实现抽象工厂接口的类,受到调用者的调用从而创建对象。
抽象产品:工厂方法模式所创建的对象的超类。也就是所有具体产品的共同父类。
具体产品:实现抽象工厂接口的类。工厂模式中所有创建的对象都是具体产品的实例。
关注快乐程序员公众号,每日分享一点小知识。爱编程,爱生活!