devexpress网站开发,用wordpress制作网站模板下载,装饰公司如何拉客户,奇网企业网站管理系统前言 传统做法-if-else分支 策略模式Map字典 责任链模式 策略模式注解 物流行业中#xff0c;通常会涉及到EDI报文(XML格式文件)传输和回执接收#xff0c;每发送一份EDI报文#xff0c;后续都会收到与之关联的回执#xff08;标识该数据在第三方系统中的流转状态#xff…前言 传统做法-if-else分支 策略模式Map字典 责任链模式 策略模式注解 物流行业中通常会涉及到EDI报文(XML格式文件)传输和回执接收每发送一份EDI报文后续都会收到与之关联的回执标识该数据在第三方系统中的流转状态。
这里枚举几种回执类型MT1101、MT2101、MT4101、MT8104、MT8105、MT9999系统在收到不同的回执报文后会执行对应的业务逻辑处理。当然实际业务场景并没有那么笼统这里以回执处理为演示案例
模拟一个回执类
Data
public class Receipt {/*** 回执信息*/String message;/*** 回执类型(MT1101、MT2101、MT4101、MT8104、MT8105、MT9999)*/String type;}模拟一个回执生成器
public class ReceiptBuilder {public static ListReceipt generateReceiptList(){//直接模拟一堆回执对象ListReceipt receiptList new ArrayList();receiptList.add(new Receipt(我是MT2101回执喔,MT2101));receiptList.add(new Receipt(我是MT1101回执喔,MT1101));receiptList.add(new Receipt(我是MT8104回执喔,MT8104));receiptList.add(new Receipt(我是MT9999回执喔,MT9999));//......return receiptList;}
}传统做法-if-else分支
ListReceipt receiptList ReceiptBuilder.generateReceiptList();
//循环处理
for (Receipt receipt : receiptList) {if (StringUtils.equals(MT2101,receipt.getType())) {System.out.println(接收到MT2101回执);System.out.println(解析回执内容);System.out.println(执行业务逻辑);} else if (StringUtils.equals(MT1101,receipt.getType())) {System.out.println(接收到MT1101回执);System.out.println(解析回执内容);System.out.println(执行业务逻辑);} else if (StringUtils.equals(MT8104,receipt.getType())) {System.out.println(接收到MT8104回执);System.out.println(解析回执内容);System.out.println(执行业务逻辑);} else if (StringUtils.equals(MT9999,receipt.getType())) {System.out.println(接收到MT9999回执);System.out.println(解析回执内容);System.out.println(执行业务逻辑);System.out.println(推送邮件);}// ......未来可能还有好多个else if
}在遇到if-else的分支业务逻辑比较复杂时我们都习惯于将其抽出一个方法或者封装成一个对象去调用这样整个if-else结构就不会显得太臃肿。
就上面例子当回执的类型越来越多时分支else if 就会越来越多每增加一个回执类型就需要修改或添加if-else分支违反了开闭原则对扩展开放对修改关闭
我们知道 策略模式的目的是封装一系列的算法它们具有共性可以相互替换也就是说让算法独立于使用它的客户端而独立变化客户端仅仅依赖于策略接口 。
在上述场景中我们可以把if-else分支的业务逻辑抽取为各种策略但是不可避免的是依然需要客户端写一些if-else进行策略选择的逻辑我们可以将这段逻辑抽取到工厂类中去这就是策略模式简单工厂代码如下
策略接口
/*** Description: 回执处理策略接口* Auther: wuzhazha*/
public interface IReceiptHandleStrategy {void handleReceipt(Receipt receipt);}策略接口实现类也就是具体的处理者
public class Mt2101ReceiptHandleStrategy implements IReceiptHandleStrategy {Overridepublic void handleReceipt(Receipt receipt) {System.out.println(解析报文MT2101: receipt.getMessage());}}public class Mt1101ReceiptHandleStrategy implements IReceiptHandleStrategy {Overridepublic void handleReceipt(Receipt receipt) {System.out.println(解析报文MT1101: receipt.getMessage());}}public class Mt8104ReceiptHandleStrategy implements IReceiptHandleStrategy {Overridepublic void handleReceipt(Receipt receipt) {System.out.println(解析报文MT8104: receipt.getMessage());}}public class Mt9999ReceiptHandleStrategy implements IReceiptHandleStrategy {Overridepublic void handleReceipt(Receipt receipt) {System.out.println(解析报文MT9999: receipt.getMessage());}}策略上下文类(策略接口的持有者)
/*** Description: 上下文类持有策略接口* Auther: wuzhazha*/
public class ReceiptStrategyContext {private IReceiptHandleStrategy receiptHandleStrategy;/*** 设置策略接口* param receiptHandleStrategy*/public void setReceiptHandleStrategy(IReceiptHandleStrategy receiptHandleStrategy) {this.receiptHandleStrategy receiptHandleStrategy;}public void handleReceipt(Receipt receipt){if (receiptHandleStrategy ! null) {receiptHandleStrategy.handleReceipt(receipt);}}
}策略工厂
/*** Description: 策略工厂* Auther: wuzhazha*/
public class ReceiptHandleStrategyFactory {private ReceiptHandleStrategyFactory(){}public static IReceiptHandleStrategy getReceiptHandleStrategy(String receiptType){IReceiptHandleStrategy receiptHandleStrategy null;if (StringUtils.equals(MT2101,receiptType)) {receiptHandleStrategy new Mt2101ReceiptHandleStrategy();} else if (StringUtils.equals(MT8104,receiptType)) {receiptHandleStrategy new Mt8104ReceiptHandleStrategy();}return receiptHandleStrategy;}
}客户端
public class Client {public static void main(String[] args) {//模拟回执ListReceipt receiptList ReceiptBuilder.generateReceiptList();//策略上下文ReceiptStrategyContext receiptStrategyContext new ReceiptStrategyContext();for (Receipt receipt : receiptList) {//获取并设置策略IReceiptHandleStrategy receiptHandleStrategy ReceiptHandleStrategyFactory.getReceiptHandleStrategy(receipt.getType());receiptStrategyContext.setReceiptHandleStrategy(receiptHandleStrategy);//执行策略receiptStrategyContext.handleReceipt(receipt);}}
}解析报文MT2101:我是MT2101回执报文喔 解析报文MT8104:我是MT8104回执报文喔
由于我们的目的是消除if-else那么这里需要将ReceiptHandleStrategyFactory策略工厂进行改造下采用字典的方式存放我的策略而Map具备key-value结构采用Map是个不错选择。
稍微改造下代码如下
/*** Description: 策略工厂* Auther: wuzhazha*/
public class ReceiptHandleStrategyFactory {private static MapString,IReceiptHandleStrategy receiptHandleStrategyMap;private ReceiptHandleStrategyFactory(){this.receiptHandleStrategyMap new HashMap();this.receiptHandleStrategyMap.put(MT2101,new Mt2101ReceiptHandleStrategy());this.receiptHandleStrategyMap.put(MT8104,new Mt8104ReceiptHandleStrategy());}public static IReceiptHandleStrategy getReceiptHandleStrategy(String receiptType){return receiptHandleStrategyMap.get(receiptType);}
}经过对策略模式简单工厂方案的改造我们已经消除了if-else的结构每当新来了一种回执只需要添加新的回执处理策略并修改ReceiptHandleStrategyFactory中的Map集合。
如果要使得程序符合开闭原则则需要调整ReceiptHandleStrategyFactory中处理策略的获取方式通过反射的方式获取指定包下的所有IReceiptHandleStrategy实现类然后放到字典Map中去。
责任链模式 责任链模式是一种对象的行为模式。在责任链模式里很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递直到链上的某一个对象决定处理此请求。
发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任
回执处理者接口
/*** Description: 抽象回执处理者接口* Auther: wuzhazha*/
public interface IReceiptHandler {void handleReceipt(Receipt receipt,IReceiptHandleChain handleChain);}
责任链接口/*** Description: 责任链接口* Auther: wuzhazha*/
public interface IReceiptHandleChain {void handleReceipt(Receipt receipt);
}责任链接口实现类
/*** Description: 责任链实现类* Auther: wuzhazha*/
public class ReceiptHandleChain implements IReceiptHandleChain {//记录当前处理者位置private int index 0;//处理者集合private static ListIReceiptHandler receiptHandlerList;static {//从容器中获取处理器对象receiptHandlerList ReceiptHandlerContainer.getReceiptHandlerList();}Overridepublic void handleReceipt(Receipt receipt) {if (receiptHandlerList !null receiptHandlerList.size() 0) {if (index ! receiptHandlerList.size()) {IReceiptHandler receiptHandler receiptHandlerList.get(index);receiptHandler.handleReceipt(receipt,this);}}}
}
具体回执处理者public class Mt2101ReceiptHandler implements IReceiptHandler {Overridepublic void handleReceipt(Receipt receipt, IReceiptHandleChain handleChain) {if (StringUtils.equals(MT2101,receipt.getType())) {System.out.println(解析报文MT2101: receipt.getMessage());}//处理不了该回执就往下传递else {handleChain.handleReceipt(receipt);}}
}public class Mt8104ReceiptHandler implements IReceiptHandler {Overridepublic void handleReceipt(Receipt receipt, IReceiptHandleChain handleChain) {if (StringUtils.equals(MT8104,receipt.getType())) {System.out.println(解析报文MT8104: receipt.getMessage());}//处理不了该回执就往下传递else {handleChain.handleReceipt(receipt);}}
}责任链处理者容器(如果采用spring,则可以通过依赖注入的方式获取到IReceiptHandler的子类对象)
/*** Description: 处理者容器* Auther: wuzhazha*/
public class ReceiptHandlerContainer {private ReceiptHandlerContainer(){}public static ListIReceiptHandler getReceiptHandlerList(){ListIReceiptHandler receiptHandlerList new ArrayList();receiptHandlerList.add(new Mt2101ReceiptHandler());receiptHandlerList.add(new Mt8104ReceiptHandler());return receiptHandlerList;}}客户端
public class Client {public static void main(String[] args) {//模拟回执ListReceipt receiptList ReceiptBuilder.generateReceiptList();for (Receipt receipt : receiptList) {//回执处理链对象ReceiptHandleChain receiptHandleChain new ReceiptHandleChain();receiptHandleChain.handleReceipt(receipt);}}
}解析报文MT2101:我是MT2101回执报文喔 解析报文MT8104:我是MT8104回执报文喔
通过责任链的处理方式if-else结构也被我们消除了每当新来了一种回执只需要添加IReceiptHandler实现类并修改ReceiptHandlerContainer处理者容器即可如果要使得程序符合开闭原则则需要调整ReceiptHandlerContainer中处理者的获取方式通过反射的方式获取指定包下的所有IReceiptHandler实现类。
这里使用到了一个反射工具类用于获取指定接口的所有实现类
/*** Description: 反射工具类* Auther: wuzhazha*/
public class ReflectionUtil {/*** 定义类集合用于存放所有加载的类*/private static final SetClass? CLASS_SET;static {//指定加载包路径CLASS_SET getClassSet(com.yaolong);}/*** 获取类加载器* return*/public static ClassLoader getClassLoader(){return Thread.currentThread().getContextClassLoader();}/*** 加载类* param className 类全限定名称* param isInitialized 是否在加载完成后执行静态代码块* return*/public static Class? loadClass(String className,boolean isInitialized) {Class? cls;try {cls Class.forName(className,isInitialized,getClassLoader());} catch (ClassNotFoundException e) {throw new RuntimeException(e);}return cls;}public static Class? loadClass(String className) {return loadClass(className,true);}/*** 获取指定包下所有类* param packageName* return*/public static SetClass? getClassSet(String packageName) {SetClass? classSet new HashSet();try {EnumerationURL urls getClassLoader().getResources(packageName.replace(.,/));while (urls.hasMoreElements()) {URL url urls.nextElement();if (url ! null) {String protocol url.getProtocol();if (protocol.equals(file)) {String packagePath url.getPath().replace(%20,);addClass(classSet,packagePath,packageName);} else if (protocol.equals(jar)) {JarURLConnection jarURLConnection (JarURLConnection) url.openConnection();if (jarURLConnection ! null) {JarFile jarFile jarURLConnection.getJarFile();if (jarFile ! null) {EnumerationJarEntry jarEntries jarFile.entries();while (jarEntries.hasMoreElements()) {JarEntry jarEntry jarEntries.nextElement();String jarEntryName jarEntry.getName();if (jarEntryName.endsWith(.class)) {String className jarEntryName.substring(0, jarEntryName.lastIndexOf(.)).replaceAll(/, .);doAddClass(classSet,className);}}}}}}}} catch (IOException e) {throw new RuntimeException(e);}return classSet;}private static void doAddClass(SetClass? classSet, String className) {Class? cls loadClass(className,false);classSet.add(cls);}private static void addClass(SetClass? classSet, String packagePath, String packageName) {final File[] files new File(packagePath).listFiles(new FileFilter() {Overridepublic boolean accept(File file) {return (file.isFile() file.getName().endsWith(.class)) || file.isDirectory();}});for (File file : files) {String fileName file.getName();if (file.isFile()) {String className fileName.substring(0, fileName.lastIndexOf(.));if (StringUtils.isNotEmpty(packageName)) {className packageName . className;}doAddClass(classSet,className);} else {String subPackagePath fileName;if (StringUtils.isNotEmpty(packagePath)) {subPackagePath packagePath / subPackagePath;}String subPackageName fileName;if (StringUtils.isNotEmpty(packageName)) {subPackageName packageName . subPackageName;}addClass(classSet,subPackagePath,subPackageName);}}}public static SetClass? getClassSet() {return CLASS_SET;}/*** 获取应用包名下某父类或接口的所有子类或实现类* param superClass* return*/public static SetClass? getClassSetBySuper(Class? superClass) {SetClass? classSet new HashSet();for (Class? cls : CLASS_SET) {if (superClass.isAssignableFrom(cls) !superClass.equals(cls)) {classSet.add(cls);}}return classSet;}/*** 获取应用包名下带有某注解的类* param annotationClass* return*/public static SetClass? getClassSetByAnnotation(Class? extends Annotation annotationClass) {SetClass? classSet new HashSet();for (Class? cls : CLASS_SET) {if (cls.isAnnotationPresent(annotationClass)) {classSet.add(cls);}}return classSet;}}接下来改造ReceiptHandlerContainer
public class ReceiptHandlerContainer {private ReceiptHandlerContainer(){}public static ListIReceiptHandler getReceiptHandlerList(){ListIReceiptHandler receiptHandlerList new ArrayList();//获取IReceiptHandler接口的实现类SetClass? classList ReflectionUtil.getClassSetBySuper(IReceiptHandler.class);if (classList ! null classList.size() 0) {for (Class? clazz : classList) {try {receiptHandlerList.add((IReceiptHandler)clazz.newInstance());} catch ( Exception e) {e.printStackTrace();}}}return receiptHandlerList;}}至此该方案完美符合了开闭原则如果新增一个回执类型只需要添加一个新的回执处理器即可无需做其它改动。如新加了MT6666的回执代码如下
public class Mt6666ReceiptHandler implements IReceiptHandler {Overridepublic void handleReceipt(Receipt receipt, IReceiptHandleChain handleChain) {if (StringUtils.equals(MT6666,receipt.getType())) {System.out.println(解析报文MT6666: receipt.getMessage());}//处理不了该回执就往下传递else {handleChain.handleReceipt(receipt);}}
}策略模式注解 此方案其实和上述没有太大异同为了能符合开闭原则通过自定义注解的方式标记处理者类然后反射获取到该类集合放到Map容器中这里不再赘述
小结 if-else或switch case 这种分支判断的方式对于分支逻辑不多的简单业务还是直观高效的。对于业务复杂分支逻辑多采用适当的模式技巧会让代码更加清晰容易维护但同时类或方法数量也是倍增的。我们需要对业务做好充分分析避免一上来就设计模式避免过度设计 文章转载自: http://www.morning.lqlc.cn.gov.cn.lqlc.cn http://www.morning.znlhc.cn.gov.cn.znlhc.cn http://www.morning.elmtw.cn.gov.cn.elmtw.cn http://www.morning.lmdfj.cn.gov.cn.lmdfj.cn http://www.morning.dgwrz.cn.gov.cn.dgwrz.cn http://www.morning.nysjb.cn.gov.cn.nysjb.cn http://www.morning.xdpjf.cn.gov.cn.xdpjf.cn http://www.morning.wfbnp.cn.gov.cn.wfbnp.cn http://www.morning.zyndj.cn.gov.cn.zyndj.cn http://www.morning.rpjyl.cn.gov.cn.rpjyl.cn http://www.morning.wtsr.cn.gov.cn.wtsr.cn http://www.morning.kqpsj.cn.gov.cn.kqpsj.cn http://www.morning.snbq.cn.gov.cn.snbq.cn http://www.morning.dmldp.cn.gov.cn.dmldp.cn http://www.morning.cfnht.cn.gov.cn.cfnht.cn http://www.morning.rhmk.cn.gov.cn.rhmk.cn http://www.morning.gwxsk.cn.gov.cn.gwxsk.cn http://www.morning.xtkw.cn.gov.cn.xtkw.cn http://www.morning.fwlch.cn.gov.cn.fwlch.cn http://www.morning.rynrn.cn.gov.cn.rynrn.cn http://www.morning.ctlbf.cn.gov.cn.ctlbf.cn http://www.morning.bnwlh.cn.gov.cn.bnwlh.cn http://www.morning.rljr.cn.gov.cn.rljr.cn http://www.morning.nxzsd.cn.gov.cn.nxzsd.cn http://www.morning.gqddl.cn.gov.cn.gqddl.cn http://www.morning.hjwkq.cn.gov.cn.hjwkq.cn http://www.morning.xpqdf.cn.gov.cn.xpqdf.cn http://www.morning.ddtdy.cn.gov.cn.ddtdy.cn http://www.morning.zmlnp.cn.gov.cn.zmlnp.cn http://www.morning.rhmpk.cn.gov.cn.rhmpk.cn http://www.morning.xsctd.cn.gov.cn.xsctd.cn http://www.morning.xsqbx.cn.gov.cn.xsqbx.cn http://www.morning.mjmtm.cn.gov.cn.mjmtm.cn http://www.morning.xqndf.cn.gov.cn.xqndf.cn http://www.morning.rdnjc.cn.gov.cn.rdnjc.cn http://www.morning.wbqt.cn.gov.cn.wbqt.cn http://www.morning.xsymm.cn.gov.cn.xsymm.cn http://www.morning.nlgmr.cn.gov.cn.nlgmr.cn http://www.morning.rbjf.cn.gov.cn.rbjf.cn http://www.morning.sxcwc.cn.gov.cn.sxcwc.cn http://www.morning.lwmxk.cn.gov.cn.lwmxk.cn http://www.morning.tkfnp.cn.gov.cn.tkfnp.cn http://www.morning.hbxnb.cn.gov.cn.hbxnb.cn http://www.morning.qmrsf.cn.gov.cn.qmrsf.cn http://www.morning.ntlxg.cn.gov.cn.ntlxg.cn http://www.morning.rnzgf.cn.gov.cn.rnzgf.cn http://www.morning.wbfly.cn.gov.cn.wbfly.cn http://www.morning.hybmz.cn.gov.cn.hybmz.cn http://www.morning.pzrrq.cn.gov.cn.pzrrq.cn http://www.morning.cwrpd.cn.gov.cn.cwrpd.cn http://www.morning.btpll.cn.gov.cn.btpll.cn http://www.morning.junyaod.com.gov.cn.junyaod.com http://www.morning.zybdj.cn.gov.cn.zybdj.cn http://www.morning.lsjtq.cn.gov.cn.lsjtq.cn http://www.morning.wqgr.cn.gov.cn.wqgr.cn http://www.morning.qbkw.cn.gov.cn.qbkw.cn http://www.morning.yxwnn.cn.gov.cn.yxwnn.cn http://www.morning.jgcxh.cn.gov.cn.jgcxh.cn http://www.morning.bqts.cn.gov.cn.bqts.cn http://www.morning.yntsr.cn.gov.cn.yntsr.cn http://www.morning.tkztx.cn.gov.cn.tkztx.cn http://www.morning.rbsxf.cn.gov.cn.rbsxf.cn http://www.morning.sgfnx.cn.gov.cn.sgfnx.cn http://www.morning.qkgwz.cn.gov.cn.qkgwz.cn http://www.morning.gjqnn.cn.gov.cn.gjqnn.cn http://www.morning.pmbcr.cn.gov.cn.pmbcr.cn http://www.morning.gbljq.cn.gov.cn.gbljq.cn http://www.morning.xxwfq.cn.gov.cn.xxwfq.cn http://www.morning.wsxly.cn.gov.cn.wsxly.cn http://www.morning.sthgm.cn.gov.cn.sthgm.cn http://www.morning.tdldh.cn.gov.cn.tdldh.cn http://www.morning.kwz6232.cn.gov.cn.kwz6232.cn http://www.morning.ykrss.cn.gov.cn.ykrss.cn http://www.morning.jjzxn.cn.gov.cn.jjzxn.cn http://www.morning.qhrsy.cn.gov.cn.qhrsy.cn http://www.morning.w58hje.cn.gov.cn.w58hje.cn http://www.morning.tpbhf.cn.gov.cn.tpbhf.cn http://www.morning.dgxrz.cn.gov.cn.dgxrz.cn http://www.morning.kjxgc.cn.gov.cn.kjxgc.cn http://www.morning.pgfkl.cn.gov.cn.pgfkl.cn