项目中太多的if...else 添加需求 又需要添加一个 else if() ... 扩展性及其不好.
首先在知乎上看到一个大神的解决方案,非常的不错.
https://zhuanlan.zhihu.com/p/33383648
实现原理: 通过策略模式+工厂模式+反射解决了 if else 的问题
比如有N多家 银行 的 计算方法都 不同 ,如果用 if ..else 去编写代码,那会非常的不好,代码中 if .. else 会非常多 也不符合 开闭原则
比如有2家 一家是 农业银行 , 一家是 工商银行 , 用枚举来定义 银行的列表, 这样返回给前段的时候 枚举名称就是 银行的 type
自定义注解:
在策略的具体实现类上面 标注这个 注解
策略接口:
策略实现类:
通过工厂来创建对象:
ClassUtil的代码:
public class ClassUtil {public static HashMapgetClasses(String pack) {// 定义一个MAP用于存放type 和类路径的映射HashMapmap = new HashMap();// 是否循环迭代boolean recursive = true;// 获取包的名字 并进行替换String packageName = pack;String packageDirName = packageName.replace('.', '/');// 定义一个枚举的集合 并进行循环来处理这个目录下的thingsEnumerationdirs;try {dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);// 循环迭代下去while (dirs.hasMoreElements()) {// 获取下一个元素URL url = dirs.nextElement();// 得到协议的名称String protocol = url.getProtocol();// 如果是以文件的形式保存在服务器上if ("file".equals(protocol)) {// 获取包的物理路径String filePath = URLDecoder.decode(url.getFile(), "UTF-8");// 以文件的方式扫描整个包下的文件 并添加到集合中findAndAddClassesInPackageByFile(packageName, filePath,recursive, map);}}} catch (IOException e) {e.printStackTrace();}return map;}@SuppressWarnings("rawtypes")public static void findAndAddClassesInPackageByFile(String packageName,String packagePath, final boolean recursive,Map map) {
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 也不是目录就直接返回
if (!dir.exists() || !dir.isDirectory()) {
// log.warn("用户定义包名 " + packageName + " 下没有任何文件");
return;
}
// 如果存在 就获取包下的所有文件 包括目录
File[] dirfiles = dir.listFiles(new FileFilter() {
// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
public boolean accept(File file) {
return (recursive && file.isDirectory())
|| (file.getName().endsWith(".class"));
}
});
// 循环所有文件
for (File file : dirfiles) {
// 如果是目录 则继续扫描
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(
packageName + "." + file.getName(),
file.getAbsolutePath(), recursive, map);
} else {
// 如果是java类文件 去掉后面的.class 只留下类名
String className = file.getName().substring(0,
file.getName().length() - 6);
try {
String fullPath = packageName + '.' + className;
// 使用注解塞map
Class clazz = Class.forName(fullPath);
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
//可以根据类型判断 读取不同类型 注解的值 put map 中
Pay pay = (Pay)annotation;
map.put(String.valueOf(pay.value()),fullPath);
}
} catch (ClassNotFoundException e) {
// log.error("添加用户自定义视图类错误 找不到此类的.class文件");
e.printStackTrace();
}
}
}
}
}
策略上下文对象:
测试类代码:
这是一位大神实现的方式...........................................
下面来谈谈我的理解:
可以用注解来标注实现类
枚举来定义具体多少种类型
这样的话 通过注解和枚举的组合来反射实例化具体的实现类,最后调用不通的策略实现. 你get 到了 吗?