您的位置:首页 > 其它

身边的设计模式--策略模式

2016-06-29 15:44 260 查看
设计模式这么高端的东西一直不敢写,因为有很多牛人的博客已经写的很好了,所以就把自己平时用到的设计模式分享一下。

我要分享的第一个设计模式不是单例,而是策略模式。

背景

在微信公众号开发中,开发者要对用户发过了的消息进行处理。用户发过来的消息有很多种,给用户回复的消息也有很多种,这个时候就需要根据业务需求进行处理。

先来看一下用户可以发过来的消息类型

文本消息

图片消息

语音消息

视频消息

小视频消息

地理位置消息

链接消息

还有下面的事件推送消息



再来看一下可以给用户回复的消息类型



反例

针对用户发过来的消息进行回复,刚开始的设计是这个样子的。



上面的if语句有130多行。可维护性差。

策略模式



公众号中的策略模式



代码实现

回复消息基类

MessageService.java

import java.util.Map;

/**
* 微信公众号回复消息
*
* @author 程高伟
*
* @date 2016年6月29日 上午10:40:49
*/
public abstract class MessageService {
/**
* 消息请求体
*/
protected Map<String, String> requestContent;

/**
* 发送方openId
*/
protected String toUserName;
/**
* 接收方openId
*/
protected String fromUserName;
/**
* 消息创建时间
*/
protected long createTime;
/**
* 消息类型
*/
protected String msgType;
/**
* 消息编号
*/
protected String msgId;

/**
* 构造函数,将请求放进构造函数中
*
* @param requestContent
*/
public MessageService(Map<String, String> requestContent) {
this.requestContent = requestContent;

// 发送方帐号(UserName)
fromUserName = requestContent.get("FromUserName");
// 公众帐号
toUserName = requestContent.get("ToUserName");
// 时间戳
createTime = Long.parseLong(requestContent.get("CreateTime"));
// 消息类型
msgType = requestContent.get("MsgType");
// 消息id
msgId = requestContent.get("MsgId");
}

/**
* 处理不同类型的消息,然后返回结果
*
* @return 返回消息响应
*/
public abstract String response();
}


消息上下文

MessageContext.java

/**
* 消息上下文
*
* @author 程高伟
*
* @date 2016年6月29日 上午10:53:30
*/
public class MessageContext {
private MessageService service;

public MessageContext(MessageService service) {
this.service = service;
}

public String response() {
return this.service.response();
}
}


回复文本消息

TextMessageService.java

import java.util.Map;

/**
* 回复文本消息
*
* @author 程高伟
*
* @date 2016年6月28日 下午10:24:40
*/
public class TextMessageService extends MessageService {

/**
* 文本消息的消息内容
*/
private String content;

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

public TextMessageService(Map<String, String> requestContent) {
super(requestContent);
this.setContent(requestContent.get("Content"));
}

@Override
public String response() {
/*<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>
*/
// 这里是用户发什么就回复什么
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(System.currentTimeMillis());
textMessage.setMsgType(MessageUtil.MESSAGE_TEXT);
textMessage.setContent(this.getContent());
return MessageUtil.textMessageToXml(textMessage);

}

}


回复图片消息

ImageMessageService.java

import java.util.Map;

/**
* 回复图片消息
*
* @author 程高伟
*
* @date 2016年6月28日 下午10:26:32
*/
public class ImageMessageService extends MessageService {

private String picUrl;
private String mediaId;

public String getPicUrl() {
return picUrl;
}

public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}

public String getMediaId() {
return mediaId;
}

public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}

public ImageMessageService(Map<String, String> requestContent) {
super(requestContent);
this.setPicUrl(requestContent.get("PicUrl"));
this.setMediaId(requestContent.get("MediaId"));
}

@Override
public String response() {
/*<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[media_id]]></MediaId>
</Image>
</xml>
*/
// 发什么图片就回复什么图片
ImageMessage imageMessage = new ImageMessage();
imageMessage.setToUserName(fromUserName);
imageMessage.setFromUserName(toUserName);
imageMessage.setCreateTime(System.currentTimeMillis());
imageMessage.setMsgType(MessageUtil.MESSAtGE_IMAGE);
Image image = new Image();
image.setMediaId(mediaId);
imageMessage.setImage(image);
return MessageUtil.imageMessageToXml(imageMessage);

}

}


回复图文消息

NewsMessageService.java

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* 回复图文消息
*
* @author 程高伟
*
* @date 2016年6月28日 下午10:26:32
*/
public class NewsMessageService extends MessageService {

public NewsMessageService(Map<String, String> requestContent) {
super(requestContent);
// 微信会给用户回复图文消息,用户不会给微信发图文消息
}

@Override
public String response() {
// 构造图文列表
Article article = new Article();
article.setTitle("程高伟的博客");
article.setUrl("http://blog.csdn.net/frankcheng5143");
article.setPicUrl("http://avatar.csdn.net/E/B/6/1_frankcheng5143.jpg");
article.setDescription("通技术之脉络,集框架之精华,开源,分享,我在路上!");
Article article1 = new Article();
article1.setTitle("慕课网");
article1.setUrl("http://www.imooc.com/");
article1.setPicUrl(
"https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=278743832,3927440098&fm=58&s=06E6DD16CCB109825DF431C601007031");
article1.setDescription(
"慕课网(IMOOC)是国内最大的IT技能学习平台。慕课网(IMOOC)提供了丰富的移动端开发、php开发、web前端、android开发以及html5等视频教程资源公开课。");
List<Article> newsList = new ArrayList<>();
newsList.add(article);
newsList.add(article1);
// 封装图文消息
NewsMessage newsMessage = new NewsMessage();
newsMessage.setToUserName(fromUserName);
newsMessage.setFromUserName(toUserName);
newsMessage.setCreateTime(System.currentTimeMillis());
newsMessage.setMsgType(MessageUtil.MESSAGE_NEWS);
newsMessage.setArticles(newsList);
newsMessage.setArticleCount(newsList.size());
return MessageUtil.newsMessageToXml(newsMessage);

}

}


修改后的处理类

public String processRequest(HttpServletRequest request) {
Map<String, String> requestMap = MessageUtil.xmlToMap(request);
logger.info("----------用户发来的消息:{}----------", requestMap);
String response = "";
MessageContext context;
// 消息类型
String msgType = requestMap.get("MsgType");
if (StringUtils.equals(msgType, MessageUtil.MESSAGE_TEXT)) {// 文本消息
context = new MessageContext(new TextMessageService(requestMap));
response = context.response();
} else if(StringUtils.equals(msgType, MessageUtil.MESSAtGE_IMAGE)){// 图片消息
context = new MessageContext(new ImageMessageService(requestMap));
response = context.response();
}else if(StringUtils.equals(msgType, MessageUtil.MESSAGE_EVENT)){// 点击按钮
context = new MessageContext(new NewsMessageService(requestMap));
response = context.response();
}else {
// 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。
// 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,
// 微信服务器不会对此作任何处理,并且不会发起重试。
// 推荐方式 直接回复success
response = "success";
}
return response;
}


策略模式

策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。

三个角色:

环境(Context)角色:持有一个Strategy的引用。

抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。 

具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

参考文献

阎宏. Java与模式[M]. 电子工业出版社, 2002.

微信公众平开开发文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式