不懂寒暄,废话少说先看代码
这段代码一开始是给我们的商城系统中,订单模块使用的通用常量类的集合,起初还只有一小部分,所以使用起来并没有觉得很复杂,寻找一个常量时往往可以很快找到,但是随着笔者决定对公司代码review时,突然发现系统中通用常量到处都是,本着让代码变得干净漂亮的原则,决定对所有具有意义的魔法常量进行通用常量设置,结果搞了一天,突然发现原本小而美的常量类,变得臃肿而难用,再去找寻一个常量时,根本不知道自己有没有写过,而且常量的类型乱七八糟,有数组,有字符串,有Long,有Integer,还有布尔值等等...
当他们都在一个类中时,无法进行有效的分类,所以笔者想着能不能分开处理这些常量呢?比如字符串就跟字符串放一起,数组常量跟数组常量放一起,然后用一个类去管理他们?
灵感来源于昨天晚上逛掘金时看到了这篇文章,# 去掉 if...else 的七种绝佳之法... 里面详细介绍了七种去掉if...else的方式,而让我第一时间想到的是,能不能用【责任链模式】来处理我的问题?
创建一个工厂和处理类,不同类型的常量都被处理类管理,在处理类中有个通用的方法,只需要传各个类的Field的name,就可以获取它的值?好像可以,说干就干!
1,创建通用常量处理器
public abstract class GlobalHandler {
protected GlobalHandler global;
protected GlobalHandler setGlobal(GlobalHandler global){
this.global = global;
return this.global;
}
public abstract Object getValue(String name) throws NoSuchFieldException;
}
2,创建头节点
public class HeadGlobal extends GlobalHandler {
@Override
public Object getValue(String name) throws NoSuchFieldException {
String globalName = Optional.ofNullable(name)
.filter(CharSequenceUtil::isNotEmpty)
.orElseThrow(() -> new BizException("常量NAME不能为空"));
return global.getValue(globalName);
}
}
3,创建尾节点
public class TailGlobal extends GlobalHandler {
@Override
public Object getValue(String name) {
throw new BizException("当前 name[" + name + "] 没有具体的 常量 处理");
}
}
4,创建不同类型的常量容器
public class BigGlobal extends GlobalHandler {
public final BigDecimal BIG_ZERO = BigDecimal.ONE;
@Override
public Object getValue(String name) throws NoSuchFieldException{
Class<?> bigClazz = BigGlobal.class;
Field field;
try{
field = bigClazz.getDeclaredField(name);
return field.get(this);
}catch (NoSuchFieldException | IllegalAccessException ne){
return global.getValue(name);
}
}
}
public class NumGlobal extends GlobalHandler {
public final Integer NUM_INT_ZERO = 0;
@Override
public Object getValue(String name) throws NoSuchFieldException {
Class<?> numClazz = NumGlobal.class;
Field field;
try{
field = numClazz.getDeclaredField(name);
return field.get(this);
}catch (NoSuchFieldException | IllegalAccessException ne){
return global.getValue(name);
}
}
}
public class StrGlobal extends GlobalHandler {
public final String STR_ZERO = "0";
@Override
public Object getValue(String name) throws NoSuchFieldException {
Class<?> strClazz = StrGlobal.class;
Field field;
try{
field = strClazz.getDeclaredField(name);
return field.get(this);
}catch (NoSuchFieldException | IllegalAccessException ne){
return global.getValue(name);
}
}
5,创建解析工厂
public class GlobalHandlerFactory {
private final GlobalHandler head;
private GlobalHandlerFactory(){
head = new HeadGlobal();
GlobalHandler strGlobal = new StrGlobal();
GlobalHandler numGlobal = new NumGlobal();
GlobalHandler bigGlobal = new BigGlobal();
GlobalHandler tail = new TailGlobal();
head.setGlobal(strGlobal)
.setGlobal(numGlobal)
.setGlobal(bigGlobal)
.setGlobal(tail);
}
private static class SingletonGlobalHandler{
private static final GlobalHandlerFactory instance = new GlobalHandlerFactory();
}
public static GlobalHandlerFactory getInstance(){
return SingletonGlobalHandler.instance;
}
public Object getValue(String name) {
try {
return head.getValue(name);
}catch (NoSuchFieldException ne){
throw new BizException("当前 name[" + name + "] 没有具体的 常量 处理");
}
}
至此,已经将上述改造悉数完成,接下来我们写几个测试类看看如何。
6,测试代码
头结点校验空字符串可用:
尾节点校验可用:
获取真实存在的数据可用:
至此我的想法算是已经完成了,后面还在想,其实返回值可以是个Field,然后在工厂方法中统一处理,上面这些代码只是完成了我的想法的一个初步阶段,如果有人对这块代码感兴趣,可以给出更好的解决方案,欢迎评论区讨论~