责任链处理者容器(如果采用spring,则可以通过依赖注入的方式获取到IReceiptHandler的子类对象)
/** * @Description: 处理者容器 * @Auther: wuzhazha */public class ReceiptHandlerContainer { private ReceiptHandlerContainer(){} public static List<IReceiptHandler> getReceiptHandlerList(){ List<IReceiptHandler> receiptHandlerList = new ArrayList<>(); receiptHandlerList.add(new Mt2101ReceiptHandler()); receiptHandlerList.add(new Mt8104ReceiptHandler()); return receiptHandlerList; }}
客户端
public class Client { public static void main(String[] args) { //模拟回执 List<Receipt> receiptList = ReceiptBuilder.generateReceiptList(); for (Receipt receipt : receiptList) { //回执处理链对象 ReceiptHandleChain receiptHandleChain = new ReceiptHandleChain(); receiptHandleChain.handleReceipt(receipt); } }}
解析报文MT2101:我是MT2101回执报文喔解析报文MT8104:我是MT8104回执报文喔通过责任链的处理方式 , if-else结构也被我们消除了 , 每当新来了一种回执 , 只需要添加IReceiptHandler实现类并修改ReceiptHandlerContainer处理者容器即可 , 如果要使得程序符合开闭原则 , 则需要调整ReceiptHandlerContainer中处理者的获取方式 , 通过反射的方式 , 获取指定包下的所有IReceiptHandler实现类 。JAVA知音公众号内回复“后端面试” , 送你一份面试宝典
这里使用到了一个反射工具类 , 用于获取指定接口的所有实现类
/** * @Description: 反射工具类 * @Auther: wuzhazha */public class ReflectionUtil { /** * 定义类集合(用于存放所有加载的类) */ private static final Set<Class<?>> 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 Set<Class<?>> getClassSet(String packageName) { Set<Class<?>> classSet = new HashSet<>(); try { Enumeration<URL> 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) { Enumeration<JarEntry> 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(Set<Class<?>> classSet, String className) { Class<?> cls = loadClass(className,false); classSet.add(cls); } private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) { final File[] files = new File(packagePath).listFiles(new FileFilter() { @Override public 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 Set<Class<?>> getClassSet() { return CLASS_SET; } /** * 获取应用包名下某父类(或接口)的所有子类(或实现类) * @param superClass * @return */ public static Set<Class<?>> getClassSetBySuper(Class<?> superClass) { Set<Class<?>> 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 Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotationClass) { Set<Class<?>> classSet = new HashSet<>(); for (Class<?> cls : CLASS_SET) { if (cls.isAnnotationPresent(annotationClass)) { classSet.add(cls); } } return classSet; }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 经常用Redis,你知道主从复制吗?
- 在Linux系统上安装和使用dig和nslookup命令
- 用elastic-job-lite玩转SpringBoot定时器管理
- 滇红茶史追溯介绍,金丝滇红茶的功效与作用
- 冲泡绿茶用什么器具,蜜梨绿茶的做法
- 茶器的实用性与美感,关于紫砂壶的实用性使用功能
- 杜仲功效与作用是什么,七福饮的功效与作用
- 淳安大方茶品质特点,淳安大方茶功效与作用
- 茶的功效与作用禁忌,胖大海的禁忌与功效作用
- 茶渣的好用处,茶的环保生活茶渣妙用二