案例:经常需要从一个Map<String, String> features中获取业务标
你可能可以这样写:
features.get(Constants.KEY1);
features.get(Constants.KEY2);
features.put(Constants.KEY1, KEY1_VALUE1);
features.put(Constants.KEY2, KEY2_VALUE2);
你们的业务逻辑中可能会散落着很多个上面的features.get(xxx)的代码,看起也没有什么不好的,其中key已经收集到常量类中了,未来维护代码时若需要找每个key被哪些地方使用也能借助IDE找到,但上面的代码有3个缺点:
- 无法方便的根据
key找到哪些地方在读取map中的key,哪些地方是在向map中写入key - 对
map的写入无法做控制,可能导致map中KV的值比较脏。比如:一般大家都不允许写入null值,不允许写入空字符串,甚至若value是枚举字面值,则应该校验value,确保map的有效性 - 虽然案例中使用常量来作为key,但可能其他人写这种代码时就直接随意往
map中添加新的key,导致key泛滥,未来想去掉某个key或则修改某个key就很难了,无法做到key的白名单化
如果把这个Map结构封装成一个类,如下:
public class FeaturesWrapper{
private Map<String, String> featuresHolder;
public FeatureWrapper(Map<String, String> features) {
if (features == null) {
features = new HashMap<>();
}
this.featuresHolder = features;
}
// 取出整个features
public Map<String, String> getFeatures() {
return featuresHolder;
}
// 封装key1的读写
public String getKey1() {
return features.get(Constants.KEY1);
}
public void setKey1(String value1) {
if (StringUtils.isNotBlank(values)) {
features.put(Constants.KEY1, value1);
}
}
// 封装key2的读写
public String getKey2() {
return features.get(Constants.KEY2);
}
public void setKey2(String value2) {
if (StringUtils.isNotBlank(values)) {
features.put(Constants.KEY2, value2);
}
}
// 其他的get方法和set方法
}
这样封装后,实际使用的效果如下:
FeaturesWrapper featuresWrapper = new FeaturesWrapper(features);
featuresWrapper.getKey1();
featuresWrapper.setKey2("xxxx");
构造一次FeaturesWrapper,然后再多次使用,就优雅多了,如下几个优点:
- 对
map的读写是分开的两个独立方法,可借助IDE来快速找到哪些业务逻辑在读某个key,哪些业务逻辑在写入某个key - 每个
set方法都可以对value做精细化且独立的校验、控制、修改,保证了value的有效性,甚至可以让某个key只允许读取,不允许修改 - 能读取和写入哪些
key已经通过get和set方法固定了,避免了key的泛滥 - 写单行代码长度缩短了,敲键盘的速度都变快了