责任链模式

来源:互联网 发布:什么软件可以视频剪辑 编辑:程序博客网 时间:2024/06/06 15:37
软件设计模式大致可以分为三类,共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;@Overridepublic 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;@Overridepublic 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,扩展参数强

4 0