表驱动法, 实战中学会和 if...else 及 switch 之间进行取舍
作者:互联网
1. 概念
表驱动法
就是一种编程模式,从表里面查找信息而不使用逻辑语句。事实上,凡是能通过逻辑语句来选择的事物,都可以通过查表来选择。对简单的情况而言,使用逻辑语句更为容易和直白。但随着逻辑链的越来越复杂,查表法也就愈发显得更具吸引力。 - 引用自《代码大全》
所谓表驱动法(Table-Driven Approach), 又称之为表驱动、表驱动方法。 简单讲是指用查表的方式获取值。
2. 常用查表方式
- 直接访问(直接访问表).
- 索引访问(索引访问表)
- 分段访问(阶梯访问表)
3. 实战PK
场景描述: 根据压缩包的后缀名来判断具体调用哪个方法来进行解压
3.1 解压工具类
public class AIUtil {
private AIUtil() {}
// 解压 zip 包
public static List<String> unzip(String srcPath) {
System.out.println(format("进入 unzip 方法. srcPath={0}.", srcPath));
// 具体解压过程省略...
return Lists.newArrayList(srcPath + File.separator + "/desc");
}
// 解压 tar 包
public static List<String> untar(String srcPath, int limit) {
System.out.println(format("进入 untar 方法. srcPath={0}, limit={1}.", srcPath, limit));
// 具体解压过程省略...
return Lists.newArrayList(srcPath + File.separator + "/desc");
}
// 解压 rar 包
public static List<String> unrar(String srcPath, boolean force) {
System.out.println(format("进入 unrar 方法. srcPath={0}, force={1}.", srcPath, force));
// 具体解压过程省略...
return Lists.newArrayList(srcPath + File.separator + "/desc");
}
// 其他压缩包格式解压函数方法...
}
3.2 常规条件判断实现方式
使用常规的 if…else 条件语句进行逻辑判断
3.2.1 核心工厂方法
private static void logicJudge(String suffix, String srcPath, int limit, boolean force) {
List<String> images = null;
if (".zip".equals(suffix)) {
images = AIUtil.unzip(srcPath);
} else if (".tar".equals(suffix)) {
images = AIUtil.untar(srcPath, limit);
} else if (".rar".equals(suffix)) {
images = AIUtil.unrar(srcPath, force);
}
// 需求迭代, 现在需要支持其他格式的压缩包解压, 则此处需要新增 if...else 逻辑
System.out.println(MessageFormat.format("方法 {0} 返回值为={1}", suffix, images));
}
3.2.2 测试用例
logicJudge(".zip", "/data/zip", -1, true);
System.out.println();
logicJudge(".tar", "/data/tar", 10, true);
System.out.println();
logicJudge(".rar", "/data/rar", -1, false);
System.out.println();
3.2.3 运行结果
进入 unzip 方法. srcPath=/data/zip.
方法 .zip 返回值为=[/data/zip\/desc]
进入 untar 方法. srcPath=/data/tar, limit=10.
方法 .tar 返回值为=[/data/tar\/desc]
进入 unrar 方法. srcPath=/data/rar, force=false.
方法 .rar 返回值为=[/data/rar\/desc]
3.3 枚举访问表方式
3.3.1 核心方法
@SuppressWarnings("unchecked")
private static void tableDrive(String suffix, List<Object> params) throws Exception {
MethodEnum method = MethodEnum.suffix2Method(suffix);
List<String> images = (List<String>) AIUtil.class.getMethod(method.methodName(), method.parameterTypes()).invoke(null, params.toArray());
System.out.println(format("方法 {0} 返回值为={1}", method.methodName(), images));
}
3.3.2 核心枚举类表
public enum MethodEnum {
/** zip 包 */
UNZIP(".zip", "unzip", String.class),
/** tar 包 */
UNTAR(".tar", "untar", String.class, int.class),
/** rar 包 */
UNRAR(".rar", "unrar", String.class, boolean.class)
// 如果需要支持其他格式的压缩包解压, 只需要在此处添加对应的枚举元素即可
;
// 文件后缀名
private String suffixName;
// 执行的解压方法名
@Getter
private String methodName;
// 执行方法的参数
@Getter
private Class[] parameterTypes;
MethodEnum(String suffixName, String methodName, Class... parameterTypes) {
this.suffixName = suffixName;
this.methodName = methodName;
this.parameterTypes = parameterTypes;
}
public static MethodEnum suffix2Method(String suffixName) {
for (MethodEnum method : MethodEnum.values()) {
if (method.suffixName.equals(suffixName)) {
return method;
}
}
throw new IllegalArgumentException(suffixName);
}
}
特别说明:
parameterTypes 填写顺序需要和具体解压方法的入参保持一致
3.3.3 测试用例
tableDrive(".zip", Lists.newArrayList("/data/zip"));
System.out.println();
tableDrive(".tar", Lists.newArrayList("/data/tar", 10));
System.out.println();
tableDrive(".rar", Lists.newArrayList("/data/rar", false));
System.out.println();
3.3.4 运行结果
进入 unzip 方法. srcPath=/data/zip.
方法 unzip 返回值为=[/data/zip\/desc]
进入 untar 方法. srcPath=/data/tar, limit=10.
方法 untar 返回值为=[/data/tar\/desc]
进入 unrar 方法. srcPath=/data/rar, force=false.
方法 unrar 返回值为=[/data/rar\/desc]
3.4 枚举访问表方式(优化版)
3.4.1 核心方法
private static void tableDrive(String suffix, List<Object> params) throws Exception {
List<String> images = (List<String>) METHODS_MAP.get(suffix).exeMethod().invoke(null, params.toArray());
System.out.println(format("方法 {0} 返回值为={1}", suffix, images));
}
3.4.2 方法接口类
反射生成具体的解压执行方法
public interface IMethod {
// 反射生成解压具体执行方法
Method exeMethod() throws Exception;
}
3.4.3 核心枚举类表
public enum MethodEnum implements IMethod {
/** zip 包 */
UNZIP(".zip") {
@Override
public Method exeMethod() throws Exception {
return UNZIP_TOOP_CLASS.getMethod("unzip", String.class);
}
},
/** tar 包 */
UNTAR(".tar") {
@Override
public Method exeMethod() throws Exception {
return UNZIP_TOOP_CLASS.getMethod("untar", String.class, int.class);
}
},
/** rar 包 */
UNRAR(".rar") {
@Override
public Method exeMethod() throws Exception {
return UNZIP_TOOP_CLASS.getMethod("unrar", String.class, boolean.class);
}
}
;
// 压缩包解压工具类类名
private static final Class<?> UNZIP_TOOP_CLASS = AIUtil.class;
// 具体解压方法名和对应枚举映射集
public static final Map<String, IMethod> METHODS_MAP = Maps.newHashMap();
static {
for (MethodEnum method : MethodEnum.values()) {
METHODS_MAP.put(method.suffixName, method);
}
}
// 文件后缀名
private String suffixName;
MethodEnum(String suffixName) {
this.suffixName = suffixName;
}
}
3.5 枚举访问表方式(升级版)
3.5.1 核心方法
private static void tableDrive(String suffix, List<Object> params) throws Exception {
List<String> images = (List<String>) METHODS_MAP.get(suffix).exeMethod().invoke(null, params.toArray());
System.out.println(format("方法 {0} 返回值为={1}", suffix, images));
}
3.5.2 方法接口类
反射生成具体的解压执行方法
public interface IMethod {
// 反射生成解压具体执行方法
Method exeMethod() throws Exception;
}
3.5.3 核心枚举类表
public enum MethodEnum implements IMethod {
/** zip 包 */
UNZIP(".zip") {
@Override
public Method exeMethod() throws Exception {
return UNZIP_METHOD;
}
},
/** tar 包 */
UNTAR(".tar") {
@Override
public Method exeMethod() throws Exception {
return UNTAR_METHOD;
}
},
/** rar 包 */
UNRAR(".rar") {
@Override
public Method exeMethod() throws Exception {
return UNRAR_METHOD;
}
}
;
// 具体解压方法名和对应枚举映射集
public static final Map<String, IMethod> METHODS_MAP = Maps.newHashMap();
private static Method UNZIP_METHOD, UNTAR_METHOD, UNRAR_METHOD;
static {
// 压缩包解压工具类类名
final Class<?> unzipToolClz = AIUtil.class;
try {
// 把耗时的反射代码挪到类初始化的时候执行
UNZIP_METHOD = unzipToolClz.getMethod("unzip", String.class);
UNTAR_METHOD = unzipToolClz.getMethod("untar", String.class, int.class);
UNRAR_METHOD = unzipToolClz.getMethod("unrar", String.class, boolean.class);
// 若要支持其他格式的压缩包, 此处也需反射获取对应的解压方法
for (MethodEnum method : MethodEnum.values()) {
METHODS_MAP.put(method.suffixName, method);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
// 文件后缀名
private String suffixName;
MethodEnum(String suffixName) {
this.suffixName = suffixName;
}
}
3.6 哈希索引访问表方式(最终版)-推荐
3.6.1 核心哈希索引表
// 具体解压方法名和对应枚举映射集
public static final Map<String, Method> METHODS_MAP = Maps.newHashMap();
static {
// 压缩包解压工具类类名
final Class<?> unzipToolClz = AIUtil.class;
try {
// 把耗时的反射代码挪到类初始化的时候执行
METHODS_MAP.put(".zip", unzipToolClz.getMethod("unzip", String.class));
METHODS_MAP.put(".tar", unzipToolClz.getMethod("untar", String.class, int.class));
METHODS_MAP.put(".rar", unzipToolClz.getMethod("unrar", String.class, boolean.class));
// 若要支持其他格式的压缩包, 此处也需反射获取对应的解压方法
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
3.6.2 核心方法
private static void tableDrive(String suffix, List<Object> params) throws Exception {
List<String> images = (List<String>) METHODS_MAP.get(suffix).invoke(null, params.toArray());
System.out.println(format("方法 {0} 返回值为={1}", suffix, images));
}
标签:解压,...,String,else,public,switch,srcPath,suffixName,class 来源: https://blog.csdn.net/u010979642/article/details/102746939