身边的设计模式--策略模式
2016-06-29 15:44
260 查看
设计模式这么高端的东西一直不敢写,因为有很多牛人的博客已经写的很好了,所以就把自己平时用到的设计模式分享一下。
我要分享的第一个设计模式不是单例,而是策略模式。
先来看一下用户可以发过来的消息类型
文本消息
图片消息
语音消息
视频消息
小视频消息
地理位置消息
链接消息
还有下面的事件推送消息
再来看一下可以给用户回复的消息类型
上面的if语句有130多行。可维护性差。
公众号中的策略模式
MessageService.java
消息上下文
MessageContext.java
回复文本消息
TextMessageService.java
回复图片消息
ImageMessageService.java
回复图文消息
NewsMessageService.java
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
微信公众平开开发文档
我要分享的第一个设计模式不是单例,而是策略模式。
背景
在微信公众号开发中,开发者要对用户发过了的消息进行处理。用户发过来的消息有很多种,给用户回复的消息也有很多种,这个时候就需要根据业务需求进行处理。先来看一下用户可以发过来的消息类型
文本消息
图片消息
语音消息
视频消息
小视频消息
地理位置消息
链接消息
还有下面的事件推送消息
再来看一下可以给用户回复的消息类型
反例
针对用户发过来的消息进行回复,刚开始的设计是这个样子的。上面的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.微信公众平开开发文档
相关文章推荐
- PropertyChangeListener简单理解
- 什么是设计模式
- 设计模式之创建型模式 - 特别的变量问题
- 七、设计模式——装饰模式
- 设计模式总结
- 设计模式之创建型模式
- 浅谈设计模式的学习
- Ruby设计模式编程之适配器模式实战攻略
- 实例讲解Ruby使用设计模式中的装饰器模式的方法
- 设计模式中的模板方法模式在Ruby中的应用实例两则
- Ruby设计模式编程中对外观模式的应用实例分析
- 实例解析Ruby设计模式编程中Strategy策略模式的使用
- Ruby中使用设计模式中的简单工厂模式和工厂方法模式
- Ruby使用设计模式中的代理模式与装饰模式的代码实例
- 详解组合模式的结构及其在Ruby设计模式编程中的运用
- C# 设计模式系列教程-建造者模式
- C#编程中使用设计模式中的原型模式的实例讲解
- 使用设计模式中的工厂方法模式进行C#编程的示例讲解
- 实例解析C#设计模式编程中简单工厂模式的使用
- 详解C#设计模式编程中生成器模式的使用