1. 程式人生 > >責任鏈模式和工廠模式在處理被動響應訊息中的應用

責任鏈模式和工廠模式在處理被動響應訊息中的應用

        在公眾號建設中,傳送被動響應訊息是最核心的環節,使用者主動發給微信的訊息經微信伺服器處理後,統一變成xml格式的報文,微信公眾平臺後臺需要對這些報文進行分別處理,然後組織響應報文響應給使用者,同時針對某些特殊操作的行為需要修改資料庫的某些資訊。

       綜合來看,微信公眾平臺對上行訊息的處理流程分為以下幾個部分:1)上行訊息入庫;2)資料庫狀態修改;3)返回應答訊息;4)應答訊息入庫。

      這四個部分是一個序列流程,很適合用責任鏈模式處理,責任鏈模式的相關內容這裡不仔細講解了(讀者感興趣可以上網去查),它的使用大致可以總結為:1)定義抽象類,例如AbstractMessageHandler,持有自己的引用,定義公用的抽象方法handleMessage();2)定義具體處理類,例如資料庫處理類、狀態處理器類、應答訊息處理器類等,分別整合抽象類,實現各自的處理方法;3)使用時需要制定責任鏈模式前驅物件的後繼物件,才能將下一步操作轉交出去。

     (1)責任鏈模式的實際應用如下:

               定義抽象類:   (可以看到它持有自己的引用)  

/**
 * 
 * @類名: AbstracMessageHandler.java 
 * @描述:責任鏈模式的抽象處理器
 * @作者: mxyanx
 * @修改日期: 2015年3月2日
 */
public abstract class AbstractMessageHandler
{
    
    
    protected AbstractMessageHandler successor;
    
    public abstract String handleMessage(String requestXmlData,BaseMessage baseMessage,String responseMessage) throws IOException;

    public AbstractMessageHandler getSuccessor()
    {
        return successor;
    }

    public void setSuccessor(AbstractMessageHandler successor)
    {
        this.successor = successor;
    }
    
}
           定義具體實現類之一:訊息入庫
/**
 * 
 * @類名: Message2DBHandler.java 
 * @描述:責任鏈模式處理的第一個環節,專門針對訊息入庫
 * @作者: mxyanx
 * @修改日期: 2015年3月2日
 */
@Component
public class Message2DBHandler extends AbstractMessageHandler
{
    
    private static final Logger logger = Logger.getLogger(Message2DBHandler.class);

    @Override
    public String handleMessage(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException
    {
        //資料庫處理
        ......
        //如果有後繼處理器,則返回下一個處理器的結果
        if(this.getSuccessor() != null){
            return this.getSuccessor().handleMessage(requestXmlData, baseMessage,responseMessageStr);
        }else{
            return responseMessageStr;
        }
    }
}

            定義具體實現類之二:狀態處理
/**
 * 
 * @類名: MessageStatusHandler.java 
 * @描述:責任鏈模式處理的第二個環節,專門針對事件型別的訊息修改狀態
 * @作者: mxyanx
 * @修改日期: 2015年3月2日
 */
@Component
public class MessageStatusHandler extends AbstractMessageHandler
{
    
    private static final Logger logger = Logger.getLogger(<span style="font-family: Arial, Helvetica, sans-serif;">MessageStatusHandler</span>.class);

    @Override
    public String handleMessage(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException
    {
        //狀態處理
        if (baseMessage.getMsgType().equalsIgnoreCase("event"))
        {
        	......
        }
        //如果有後繼處理器,則返回下一個處理器的結果
        if(this.getSuccessor() != null){
            return this.getSuccessor().handleMessage(requestXmlData, baseMessage,responseMessageStr);
        }else{
            return responseMessageStr;
        }
    }
}

           定義具體實現類之三:組織被動響應訊息返回
/**
 * 
 * @類名: MessageResponseHandler.java 
 * @描述:責任鏈模式處理的第三個環節,組織被動響應訊息
 * @作者: mxyanx
 * @修改日期: 2015年3月2日
 */
@Component
public class MessageResponseHandler extends AbstractMessageHandler
{
    
    private static final Logger logger = Logger.getLogger(MessageResponseHandler.class);

    @Override
    public String handleMessage(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException
    {
        //生成被動響應訊息
       ......
        //如果有後繼處理器,則返回下一個處理器的結果
        if(this.getSuccessor() != null){
            return this.getSuccessor().handleMessage(requestXmlData, baseMessage,responseMessageStr);
        }else{
            return responseMessageStr;
        }
    }
}

         最後來看看責任鏈模式的初始化呼叫:(設定了每個處理器的後繼者,正是通過父類持有的引用來實現的)
@Service
public class MessageService
{
    private Logger logger = Logger.getLogger(MessageService.class);

    /**
     * 
     * 功能描述:根據上行訊息返回下行訊息
     * 
     * @param requestXml
     * @return
     * @throws StreamException
     * @throws IOException
     */
    public String getResponseXml(String requestXmlData) throws StreamException, IOException
    {
        String responseMessageStr = StringUtils.EMPTY;
        BaseMessage baseMessage = XmlUtil.getBaseMessage(requestXmlData);
        AbstractMessageHandler message2DBHandler = new Message2DBHandler();
        AbstractMessageHandler messageStatusHandler = new MessageStatusHandler();
        AbstractMessageHandler messageResponseHandler = new MessageResponseHandler();
        //設定訊息入庫的後繼操作為修改資料庫狀態
        message2DBHandler.setSuccessor(messageStatusHandler);
        //設定修改資料庫狀態的後繼操作為返回被動響應訊息
        messageStatusHandler.setSuccessor(messageResponseHandler);
        message2DBHandler.handleMessage(requestXmlData, baseMessage,responseMessageStr);
        logger.info("responseMessageStr:"+responseMessageStr);
        return responseMessageStr;
    }
}

     (2)工廠模式的應用

               針對使用者上行的不同型別的報文,我們可以用工廠模式返回不同的處理物件,這些處理物件都繼承了同樣的抽象類,重寫了同一個介面方法,從而在具體方法中處理不同的業務邏輯。這裡抽象類的作用是用來抽取公共方法,全部實現過程如下:

            定義訊息處理器介面:  

/**
 * 
 * @類名: IMessageProcessor.java 
 * @描述:處理器介面,用來處理不同的應答訊息
 * @作者: mxyanx
 * @修改日期: 2015年3月3日
 */
public interface IMessageProcessor
{
    void process(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException;
}

          定義抽象類,實現處理器介面,同時定義公共方法:

/**
 * 
 * @類名: PublicProcessor.java 
 * @描述:訊息公共處理器,提供各種方法供具體處理器呼叫
 * @作者: mxyanx
 * @修改日期: 2015年3月5日
 */
@Component
public class PublicProcessor implements IMessageProcessor
{
    
   

    public void process(String requestXmlData, BaseMessage baseMessage, String responseMessageStr) throws IOException
    {
        // TODO Auto-generated method stub
        
    }

    /**
     * 
     * 功能描述:返回被動響應訊息,主要有兩種型別:文字型別和圖文型別
     * 
     * @return
     */
    protected String getResMessageById(String messageId, BaseMessage baseMessage)
    {
        ......
    }


    /**
     * 
     * 功能描述:應答文字訊息入庫
     * 
     * @param content
     */
    protected void insertResTextMessage2DB(String content, BaseMessage baseMessage)
    {
       ......
    }


    /**
     * 
     * 功能描述:應答圖文訊息入庫
     * 
     * @param articleMessageItems
     * @param baseMessage
     */
    protected void insertResArticleMessage2DB(List<ArticleMessageItem> articleMessageItems, BaseMessage baseMessage)
    {
        ......
    }
    
    /**
     * click事件訊息型別返回
     * 
     * 功能描述:返回響應給使用者的訊息,主要有兩種型別:文字型別和圖文型別
     * 
     * @return
     */
    protected String getResMessageByName(String messageName, BaseMessage baseMessage)
    {
       ......
    }
    
    /**
     * 
     * 功能描述:判斷多客服開關是否啟用
     * @param baseMessage
     * @return
     */
   protected boolean getCustomerServiceFlag(String accountId){
       ......
   }

}

          定義工廠類,根據使用者上行訊息的內容返回不同的處理器:
/**
 * 
 * @類名: ProcessorFactory.java
 * @描述:處理器工廠類,用來返回不同的處理器
 * @作者: mxyanx
 * @修改日期: 2015年3月3日
 */
public class ProcessorFactory
{
    public static IMessageProcessor getProcessorMessage(String msgType)
    {
        if (msgType.equalsIgnoreCase("text"))
        {
            return new TextMessageProcessorImpl();
        }
        else if (msgType.equalsIgnoreCase("location"))
        {
            return new LocationMessageProcessorImpl();
        }
        else if (msgType.equalsIgnoreCase("image"))
        {
            return new ImageMessageProcessorImpl();
        }
        else if (msgType.equalsIgnoreCase("event"))
        {
            return new EventMessageProcessorImpl();
        }
        else
        {
            return null;
        }
    }

}

         定義具體的處理器類之一:文字訊息處理器
/**
 * 
 * @類名: TextMessageProcessorImpl.java
 * @描述:文字訊息處理器,生成應答訊息和應答訊息入庫
 * @作者: mxyanx
 * @修改日期: 2015年3月5日
 */
@Component
public class TextMessageProcessorImpl extends PublicProcessor
{
    private static final Logger logger = Logger.getLogger(TextMessageProcessorImpl.class);

    @Override
    public void process(String requestXmlData, BaseMessage baseMessage, String responseMessageStr) throws IOException
    {
       //處理文字訊息,這裡可能用到抽象類中的方法
       ......
       
    }

}

         定義具體的處理器之二:圖片訊息處理器

/**
 * 
 * @類名: ImageMessageProcessorImpl.java
 * @描述:圖片訊息處理器,生成應答訊息和應答訊息入庫
 * @作者: mxyanx
 * @修改日期: 2015年3月5日
 */
@Component
public class ImageMessageProcessorImpl extends PublicProcessor
{
    private static final Logger logger = Logger.getLogger(ImageMessageProcessorImpl.class);

    @Override
    public void process(String requestXmlData, BaseMessage baseMessage, String responseMessageStr) throws IOException
    {
       //處理圖片訊息,這裡可能用到抽象類中的方法
       ......
       
    }

}

         定義具體的處理器之三:地理位置訊息處理器
/**
 * 
 * @類名: LocationMessageProcessorImpl.java
 * @描述:地理位置訊息處理器,生成應答訊息和應答訊息入庫
 * @作者: mxyanx
 * @修改日期: 2015年3月5日
 */
@Component
public class LocationMessageProcessorImpl extends PublicProcessor
{
    private static final Logger logger = Logger.getLogger(ImageMessageProcessorImpl.class);

    @Override
    public void process(String requestXmlData, BaseMessage baseMessage, String responseMessageStr) throws IOException
    {
       //處理地理位置訊息,這裡可能用到抽象類中的方法
       ......
       
    }

}

     ......

         最後,看一下工廠模式是如何呼叫的:

/**
 * 
 * @類名: MessageResponseHandler.java 
 * @描述:被動響應訊息處理器,專門返回被動響應訊息
 * @作者: mxyanx
 * @修改日期: 2015年3月2日
 */
@Component
public class MessageResponseHandler extends AbstractMessageHandler
{

    @Override
    public String handleMessage(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException
    {
        //使用工廠模式,根據訊息型別返回不同的處理器組裝返回訊息
        IMessageProcessor messageProcessor = ProcessorFactory.getProcessorMessage(baseMessage.getMsgType());
        messageProcessor.process(requestXmlData, baseMessage, responseMessageStr);
        //如果有後繼處理器,則返回下一個處理器的結果
        if(this.getSuccessor() != null){
            return this.getSuccessor().handleMessage(requestXmlData, baseMessage,responseMessageStr);
        }else{
            return responseMessageStr;
        }
    }   

}

使用上述兩種設計模式,可以使得業務邏輯變得清晰,程式碼的層次感更強,希望上述介紹對讀者有幫助。