責任鏈模式

軟件設計模式大致可以分爲三類,共23種。
創建型模式:單例模式、抽象工廠模式、建造者模式、工廠模式、原型模式。
結構型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。
行爲型模式:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式、狀態模式、策略模式、責任鏈模式、訪問者模式。
其實模式這東西也有點虛,寫代碼並不一定要生搬硬套上面的模式。如何能滿足業務需求,同時又具有最大可擴展性纔是我們一直追求的目標。

責任鏈模式就是很多對象由每個對象對其下家的引用串連起來形成一條鏈,請求在這條鏈上傳遞,直到最終處理完。就象一根水管一樣,水從一端流入,會經過一系列的閥門,最終從另一端流出。如果有一個閥門關着,水都流不出來。

鏈上的節點可以控制,根據是否執行分爲兩種情況:
1)找到對應的點,執行,跳出。如:for循環的break
2)所有的節點都執行一遍,上個節點的返回結果作爲下個節點的入參

業務需求:抽獎
步驟:
1)抽獎資格判斷
a)判斷人羣
b)判斷抽獎限制(如每天只能抽3次)
c)黑名單
d)判斷中獎次數限制(如最多隻能中3次)
。。。。。。。。
2)中獎邏輯
a)根據用戶V等級進行概率過濾
b)根據抽獎概率進行過濾
3)發獎邏輯
a)取出當前獎品分佈,並選出一個獎品分佈來發獎
b)減庫存
c)發獎
d)發獎成功後的邏輯處理
e)處理其它processor中添加的callback

代碼示例 :
1. 主流程:
public class DefaultAwardCommanderProcedure implements AwardCommanderProcdure {
	private List<Commander> commanderList;
	@Override
	public AwardResult execute(Context context) {
		if(getCommanderList() == null || getCommanderList().size() == 0) {
			return AwardResultUtils.buildErrorResult(DefaultResultCode.SYSTEM_ERROR);
		}
		for(Commander commander : getCommanderList()) {
			AwardResult result = commander.execute(context);
			if(!result.isSuccess()) {
				AwardLogUtils.getAwardLog().warn("DefaultAwardCommanderProcedure.execute() return false|context=" + context + "|awardResult=[" + result + "]");
				return result;
			}
		}
		AwardLogUtils.getAwardLog().warn("DefaultAwardCommanderProcedure.execute() return success|context=[" + context + "]")
		return AwardResultUtils.buildSuccessResult();
	}

	public List<Commander> getCommanderList() {
		return commanderList;
	}
	public void setCommanderList(List<Commander> commanderList) {
		this.commanderList = commanderList;
	}

主流程bean xml配置
<!-- 默認抽獎流程 -->
	<bean id="defaultAwardCommanderProcedure" class="com.taobao.wireless.award.biz.forward.biz.procedure.impl.DefaultAwardCommanderProcedure">
		<property name="commanderList"> 
            <list> 
                <ref bean="permissionCommander" />    <!-- 抽獎邏輯 -->
                <ref bean="winCommander" />       <!-- 中獎邏輯 -->
                <ref bean="dispatchCommander" />  <!-- 發獎邏輯 -->
        	</list> 
        </property> 	
	</bean>

2. 抽獎邏輯
public class DefaultCommander implements Commander {

	private List<Processor> processorList;
	@Override
	public AwardResult execute(Context context) {
		if(getProcessorList() == null || getProcessorList().size() == 0) {
			return AwardResultUtils.buildErrorResult(DefaultResultCode.SYSTEM_ERROR);
		}
		for(Processor processor : getProcessorList()) {
			AwardResult result = processor.process(context);
			if(!result.isSuccess()) {
				return result;
			}
		}
		return AwardResultUtils.buildSuccessResult();
	}

	public List<Processor> getProcessorList() {
		return processorList;
	}

	public void setProcessorList(List<Processor> processorList) {
		this.processorList = processorList;
	}

}

xml配置
<!-- 1、判斷抽獎資格 -->
	<bean id="permissionCommander" class="com.taobao.wireless.award.biz.forward.biz.commander.impl.PermissionCommander">
		<property name="processorList">
            <list>
            	<ref bean="checkUserGroupProcessor" />   <!-- 判斷人羣 -->
            	<ref bean="awardCountingProcessor" />  <!-- 活動抽獎數計數 -->
                <ref bean="checkAndReducePermitPermissionProcessor" />      <!-- 判斷是否有抽獎權限,有則減權限 -->
                <ref bean="checkBlacklistPermissionProcessor" />      <!-- 黑名單 -->
                <ref bean="checkWinCountPermissionProcessor" />      <!-- 判斷中獎次數限制(如最多隻能中3次) -->
        	</list> 
        </property> 
	</bean>
	

3. 具體的原子執行邏輯
接口:
public interface Processor {
	/**
	 * 處理邏輯
	 * @param context
	 * @return
	 */
	AwardResult process(Context context);
	
}
子類則根據具體的業務功能單獨封裝實現。

總結:
1)串行執行所有的邏輯,如果有一個條件不滿足或拋異常,則返回false,跳出流程
2)擴展性好,能很好地滿足各種業務變更,只需要實現相應的接口,增加相應的xml配置即可
3)直觀,將日誌統一放到一個日誌類管理
4)定義上下文參數類Context,擴展參數強

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章