`
tsface
  • 浏览: 8969 次
  • 性别: Icon_minigender_1
  • 来自: 西安
最近访客 更多访客>>
社区版块
存档分类
最新评论

[1]设计模式——简单工厂模式

阅读更多

简单工厂模式

    简单工厂模式:的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了和具体产品的依赖。

 

    上面的这句话怎么理解呢?我们看看下面这段代码,这段代码是客户端的业务逻辑代码:

     

// 文本消息  
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

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics