1. 什么是策略模式
简单的讲就是实现一个问题的多种方法就是策略设计模式,我们在开发微信公众号时,有一组被动接收微信消息的接口(例如:普通文本消息、关注事件消息、取消关注事件消息……),针对不同的消息有多种处理方式,有处理文本有处理关注事件的等等我们使用的逻辑算法都不一样,当然啦业务逻辑也不一样啦。像这种情况我们可以尝试使用策略模式
来进行设计,其中策略模式
属于行为型设计模式类型。设计模式的主要原则之一就是封装变化的内容,对于发送到PHP类的不同类型的请求,分别有不同的算法来处理。类图如下:
在策略模式
在模式中我们要避免在context参与者中使用条件语句或case语句,使用条件语句可能会导致维护想当困难。如果要改变一个策略(封装的算法逻辑)或新增一个具体的算法策略时,那么context参与者就会被动的再去添加这个具体的策略,并对其进行维护。如果实现某个问题的具体策略想当的多那么context就会变得臃肿使其难以维护,同时也违反了面向对象编程中的开放封闭原则
不是吗?如果读者还不懂什么是开发封闭原则,建议去看doris的http://blog.csdn.net/dorisnzy/article/details/76222881的博客,这样更有助于理解设计模式开发中的奥妙。
2. 不良的代码设计
接下来演示一下工作中没有采用策略模式伪代码。案例为被动接收微信事件消息,伪代码如下:
<?php
/**
* 被动接收微信消息
* @author doris <[email protected]>
*/
class WechatRequest
{
// 接收到的消息体
private $msg;
/**
* 消息入口
*/
public function index()
{
$this->msg = file_get_contents('php://input');
// ……xml处理msg信息省略……
switch($this->msg['msgtype']) {
case 'text':
// 处理普通文本消息的业务逻辑算法
$this->text();
break;
case 'image':
// 处理图片的业务逻辑算法
$this->image();
break;
// ……等等其它业务逻辑算法……
}
}
/**
* 处理text文本消息
*/
private function text()
{
// 业务逻的处理
}
/**
* 处理image文本
*/
private function iamge()
{
// 业务逻辑的处理
}
}
// 调用
$wechat = new WechatRequest;
$wechat->index();
代码分析:
这种开发把所有接收不同类型的消息都集中到了一个类中完成会使得业务代码会越来越臃肿,可扩展性不好,可读性也不好,如果下一个开发者来维护这个代码会很难入手。
3. 使用策略模式对代码进行优化
策略模式中参与者有2个身份,一个是实现某个问题的详细策略,一个是context参与者,伪代码如下:
(1)详细策略具体实现的算法组参与者
<?php
/**
* 策略接口规范要实现的方法
* @author doris <[email protected]>
*/
interface class IrequestStrategy
{
/**
* 实现接收各类型消息并处理
*/
abstract public function dispose();
}
/**
* 接收并处理普通文本消息
* @author doris <[email protected]>
*/
class Text implememt IrequestStrategy
{
/**
* 处理普通文本消息
*/
public function dispose()
{
// 实现具体的业务逻辑
}
}
/**
* 接收并处理图片消息
* @author doris <[email protected]>
*/
class Image implement IrequestStrategy
{
public function dispose()
{
// 实现具体的业务逻辑
}
}
// 处理其它消息类型……
(2)context参与者
<?php
/**
* 根据上下文实现具体的策略
* @author doris <[email protected]>
*/
class Context
{
private $strategy;
/**
* 初始化工作
* @param object $strategy 实现具体消息的详细策略算法的策略对象
*/
public function __construct(IrequestStrategy $strategy)
{
$this->strategy = $strategy;
}
/**
* 接收并处理各类型的消息
*/
public function dispose()
{
$this->strategy->dispose();
}
}
(3)client端调用
<?php
$msg = file_get_contents('php://input');
// ……xml处理msg信息省略……
switch($msg['msgtype']) {
case 'text':
// 处理普通文本消息的业务逻辑算法
$strategy = new Text;
;
break;
case 'image':
// 处理图片的业务逻辑算法
$strategy = new Image;
break;
// ……等等其它业务逻辑算法……
}
$context = new Context($strategy);
$context->dispose();
代码分析:
这种代码的设计可以将各个类型的消息抽离出来分别实现各种不同的算法,代码看起来非常简洁,可扩展性好,可读性也好,如果什么时候微信公众号再加一个其它消息类型,不需要对原有的业务代码进行修改,只需要扩展一个具体的策略算法就能够轻松的实现。
扩展:
除了像接收微信并处理微信各类型的消息事件时可以用策略模式以外,比如系统中使用多种缓存机制、多种数据库机制、及数据库增删查改等等这些,都可以使用策略模式来进行设计。
4. 补充说明
客户端调用的时候如果再加一个其它的消息类型时还是会去修改原有的代码,并且当消息类型非常多的时候代码也还是会变得越来越臃肿,所以我们还可以用简单工厂模式对其进行设计。这部分的实现请参考doris的博客初探面向对象与设计模式-简单工厂模式。
完!