简单工厂模式
简单工厂模式:的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了和具体产品的依赖。
上面的这句话怎么理解呢?我们看看下面这段代码,这段代码是客户端的业务逻辑代码:
// 文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { return buildTextMsgXml(requestMap); } // 图片消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { respContent = "/:p-(您发送的是图片消息!暂时处理不了哎!"; } // 地理位置消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { respContent = "/:p-(您发送的是地理位置消息!暂时处理不了哎!"; } // 链接消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) { respContent = "/:p-(您发送的是链接消息!暂时处理不了哎!"; } // 音频消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) { espContent = "/:p-(您发送的是音频消息!暂时处理不了哎!"; } //....还有许多
这段代码是客户端的代码,很多刚开始写代码的朋友都会和我一样,用大堆的条件控制语句完成业务逻辑代码,但是这样有一个问题,如果新增了一个“消息”类型,那么我们是不是就要在客户端新增加一个if语句呢?这样写当然是没有错误的,但是它增加了代码的“Bad Smell(代码的坏味道) ”,而且增加了客户端的维护成本,也不符合软件设计的“开闭原则”。
代码如何改进,那么我们不妨采用一种简单工厂方法来消除客户端的维护成本。
首先定义一个消息处理接口:
/* * @(#)MessageHandler.java 2014-3-16 */ package com.lotus.weixin.reqhandler; import java.util.Map; /** * 消息处理接口 * @author tsface * @version 2014-3-16 * @since 1.0 */ public interface MessageHandler { /** * 生成消息的类型 * @param megType * @return */ public String buildXMlStr(Map<String, String> requestMap); }
不同消息处理类实现消息处理接口,下一个代码片段是文本消息的实现
/* * @(#)TextMsgHandlerImpl.java 2014-3-16 */ package com.lotus.weixin.reqhandler.impl; import java.util.Date; import java.util.Map; import com.avatar.gdk.util.StringUtils; import com.lotus.weixin.message.resp.TextMessage; import com.lotus.weixin.message.utils.MessageUtil; import com.lotus.weixin.reqhandler.MessageHandler; /** * 文本消息处理类 * @author tsface * @version 2014-3-16 * @since 1.0 * @see */ public class TextMsgHandlerImpl implements MessageHandler { @Override public String buildXMlStr(Map<String, String> requestMap) { // 发送方帐号(open_id) String fromUserName = requestMap.get("FromUserName"); String toUserName = requestMap.get("ToUserName"); // 消息类型 String reqContent = requestMap.get("Content"); // 回复文本消息 TextMessage textMessage = new TextMessage(); textMessage.setToUserName(fromUserName); textMessage.setFromUserName(toUserName); textMessage.setCreateTime(new Date().getTime()); textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT); textMessage.setFuncFlag(0); if(StringUtils.isNotEmpty(reqContent) ) { if("?".equals(reqContent)) { textMessage.setContent(MessageUtil.getMainMenu()); }else if("1".equals(reqContent)) { // 获取网页源代码 //String html = httpRequest("http://ip.taobao.com/service/getIpInfo.php?ip=127.0.0.1"); textMessage.setContent("你要查看的是时政新闻"); }else { textMessage.setContent(MessageUtil.getMainMenu()); } }else { textMessage.setContent(MessageUtil.getMainMenu()); } return MessageUtil.textMessageToXml(textMessage); } }
下面一步我们来封装我们的工厂类,当然工厂类代码还是存在大量的if语句,这是一种不好的做法,如何消除这种代码,我们可以利用Java中的注解,反射机制来消除,本文就不介绍了。
/* * @(#)MessageHandlerFactory.java 2014-3-16 */ package com.lotus.weixin.reqhandler; import com.lotus.weixin.message.utils.MessageUtil; import com.lotus.weixin.reqhandler.impl.LocationMsgHandlerImpl; import com.lotus.weixin.reqhandler.impl.PicMsgHandlerImpl; import com.lotus.weixin.reqhandler.impl.TextMsgHandlerImpl; import com.lotus.weixin.reqhandler.impl.VoiceMsgHandlerImpl; /** * 描述当前类的作用 * * @author tsface * @version 2014-3-16 * @since 1.0 * @see */ public class MessageHandlerFactory { /** * 构造方法私有化 */ private MessageHandlerFactory() { } /** * 生成实例的的方法 * @param msgType * @return */ public static MessageHandler createMsgHandler(String msgType) { MessageHandler handler = null; // 文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { handler = new TextMsgHandlerImpl(); } // 图片消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { handler = new PicMsgHandlerImpl(); } // 地理位置消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { handler = new LocationMsgHandlerImpl(); } // 链接消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) { } // 音频消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) { handler = new VoiceMsgHandlerImpl(); } return handler; } }
以上代码完成了我们对简单工厂的封装,下面我们看看客户端代码怎么写。有了工厂以后,我们只需用工厂产生我们需要的对象,调用接口提供的方法完成客户代码的解耦工作。
//获取消息处理接口 MessageHandler createMsgHandler = MessageHandlerFactory.createMsgHandler(msgType); String xmlStr = createMsgHandler.buildXMlStr(requestMap); f(StringUtils.isNotEmpty(xmlStr)) { return xmlStr; }else{ respContent = "/:p-(您发送的消息!暂时处理不了哎!"; }
以后即使新增了消息类型,那么客户端的代码我们就无需进行改动,只需要修改工厂类就可以实现,如果我们消除工厂类中的判断,改用读取配置文件或者注解来创建对象,那么我们代码就完全符合“对修改关闭,对增加开放”的原则了。
开闭原则:1988年,勃兰特·梅耶(Bertrand Meyer)在他的著作《面向对象软件构造(Object Oriented Software Construction)》中提出了开闭原则,它的原文是这样:“Software entities should be open for extension,but closed for modification”。翻译过来就是:“软件实体应当对扩展开放,对修改关闭”
2014/3/16 tsface 南京
hanily@msn.com
相关推荐
设计模式——抽象工厂模式源码,设计模式——抽象工厂模式源码
这个是http://blog.csdn.net/dawanganban/article/details/9875873博客中java设计模式的源代码。下载前请先看《设计模式——简单工厂》一文。
经典的设计模式————简单工厂模式,里面有实验文档和实验源代码还有课件助于你的学习
vs2010实现的软件设计模式——抽象工厂,是软件工程专业学生专业技能之一
这个是http://blog.csdn.net/dawanganban/article/details/9877593博客中java设计模式的源代码。下载前请先看《设计模式——工厂方法模式》一文。
NULL 博文链接:https://maidoudao.iteye.com/blog/1328618
设计模式C#描述之——简单工厂模式,让你学习C#的一种设计模式
Android之大话设计模式——:抽象工厂模式借鉴.pdf
这个是http://blog.csdn.net/dawanganban/article/details/9884681博客中java设计模式的源代码。下载前请先看《设计模式——工厂模式在开发中的应用》一文。
Android之大话设计模式——:抽象工厂模式参考.pdf
写博客上传的代码:blog http://blog.csdn.net/t1234xy4/article/details/52424048
主要介绍了Java设计模式——工厂设计模式详解,具有一定参考价值,需要的朋友可以了解下。
SETema5 软件设计模式——抽象工厂
java23种设计模式 工厂模式 ,抽象工厂,建造者模式,单态模式,原型模式
JAVA设计模式总结之23种设计模式 一:设计模式之六大原则 总原则:开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。...1.Abstract Factory(抽象工厂模式) 2.Adapter(适配器模式)......
简单工厂模式 工厂方法模式 抽象工厂模式 面向对象设计的基本原则: OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。 DIP(依赖倒转原则,Dependence Inversion Principle):...
工厂方法模式之所以可以解决简单工厂的模式,是因为它的实现把具体产品的创建推迟到子类中,此 时工厂类不再负责所有产品的创建,而...下面看下工厂模式 的具体实现代码(这里还是以简单工厂模式中点菜的例子来实现):
书名: 设计模式可复用面向对象软件的基础 英文原书名: Design Patterns:Elements of Reusable Object-Oriented software 作者: Erich Gamma 等 译者: 李英军 马晓星 蔡敏 刘建中 书号: 7-111-07575-7 页码: 254 定价...
完成了,但感觉这也没啥特别的,程序界面黑布隆冬的,内部结构也是最最平常的面向对象,于是我应用了《大话设计模式》这本书中的第一个模式——简单工厂模式,看上去还不错。界面的话,也就是输出的语句变了,system...
设计模式课程资料——简单工厂模式,使用Java实现,在eclipse进行编译