设计模式(英语 design pattern)是对面向对象设计中反复出现的问题的解决方案。就像下象棋时红方走中心炮,黑方就跳一个马来保护中兵一样。所以不要认为他有多深奥。首先申明设计模式不是算法,它只有适合与不适合,没有性能优劣之分。之后会用一样简单的例子来一一讲解常见的几种设计模式。
今天主要分析简单工厂模式。比如要实现一个在线支付功能(主要是支付宝支付和微信支付),如果之后还会有paypal、京东等。因为每种线上支付都自己的文档,对接起来会花费一定的时间,由于时间紧所以一人负责一个支付方式开发。小张开发支付宝,小李开发微信。小王开发结算逻辑,小王会根据用户的提交的支付方式去调用相对应的方法。你是一个技术负责人需要制定统一的调用标准,统一的返回标准,你该如何做?
简单的工厂模式就是解决这类问题的解决方案:
负责人要制定标准,要实现功能类的方法统一,返回数据统一。
第一、定义一个负责描述所有支付方式的公共接口Payment
Payment类中有支付方式和回调验证方式,让小张和小李去实现自己的业务逻辑。
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);
}
第二、实现一个简单的工厂类,负责实现创建所有实例的内部逻辑。告知小王支付类有哪些方法及入参
namespace libs\pay;
class PayFactory
{
public static function payment($type)
{
if ($type=='Alipay') {
return new Alipay();
} elseif ($type=='Wechatpay') {
return new Wechatpay();
} else {
throw new \Exception('不支持的支付方式');
}
}
}
小张的工作是去实现支付宝支付的对接:
namespace libs\pay;
class Alipay implements Payment
{
public function pay (array $input)
{
// TODO: Implement pay() method.
echo '<br/>正在与支付宝进行对接……<br/>';
echo '对接成功……<br/>';
return ['status'=>1, 'message'=>'支付宝支付成功'];
}
public function notify (array $input)
{
// TODO: Implement notify() method.
echo '<br/>正在与支付宝进行对接……<br/>';
echo '校验成功……<br/>';
return ['status'=>1, 'message'=>'支付宝回调校验成功'];
}
}
小李的工作是去实现微信支付的对接:
namespace libs\pay;
class Wechatpay implements Payment
{
public function pay (array $input)
{
// TODO: Implement pay() method.
echo '<br/>正在与微信进行对接……<br/>';
echo '对接成功……<br/>';
return ['status'=>1, 'message'=>'微信支付成功'];
}
public function notify (array $input)
{
// TODO: Implement notify() method.
echo '<br/>正在与微信进行对接……<br/>';
echo '校验成功……<br/>';
return ['status'=>1, 'message'=>'微信回调校验成功'];
}
}
小王的工作是实现订单的业务逻辑,并根据用户的选择调用不同的支付方式:
require_once ('./libs/loader/Loader.php');
spl_autoload_register('\\libs\\loader\\Loader::autoload');
use libs\pay\PayFactory;
echo '订单处理中……<br/>';
//订单信息
$input = [
'order_no' => '20000001', //订单号
'total' => '120' //金额
//……
];
//支付宝支付
$payment = PayFactory::payment('Alipay');
$payResult = $payment->pay($input);
var_dump($payResult);
//微信支付
$payment = PayFactory::payment('Wechatpay');
$payResult = $payment->pay($input);
var_dump($payResult);
整个例子的结构图:
这样实现功能类的方法统一,返回数据统一;解决了团队开发中的并行开发,缩短了开发周期,为以后扩展京东支付或paypal支付提供了规范。
以上就是一个简单工厂设计模式的一个完整例子,它主要包含三部份
Factory:工厂角色,工厂角色负责实现创建所有实例的内部逻辑。即例子中的PayFactory。
Product:抽象产品角色,抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口。即例子中的Payment。
ConcreteProduct:具体产品角色,具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。即例子中的Alipay,Wechatpay。
这样种方案能实现我们的目的,当然要感谢的动态语言以后加了paypal,只要在PayFactory中加一个elseif,然后上传即可。如果是c++,java这种项目就需要重新编译。而且如果小张加了一个paypal,项目负责人还要来改PayFactory,始终感觉不够完美。那么还有没有更好的方式呢?欢迎留言讨论!
关注快乐程序员公众号,每日分享一点小知识。爱编程,爱生活!