从Map中读写数据的逻辑封装成一个类是个优雅的选择

31 阅读2分钟

案例:经常需要从一个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个缺点:

  1. 无法方便的根据key找到哪些地方在读取map中的key,哪些地方是在向map中写入key
  2. map的写入无法做控制,可能导致map中KV的值比较脏。比如:一般大家都不允许写入null 值,不允许写入空字符串,甚至若value是枚举字面值,则应该校验value,确保map的有效性
  3. 虽然案例中使用常量来作为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,然后再多次使用,就优雅多了,如下几个优点:

  1. map的读写是分开的两个独立方法,可借助IDE来快速找到哪些业务逻辑在读某个key,哪些业务逻辑在写入某个key
  2. 每个set方法都可以对value做精细化且独立的校验、控制、修改,保证了value的有效性,甚至可以让某个key只允许读取,不允许修改
  3. 能读取和写入哪些key已经通过getset方法固定了,避免了key的泛滥
  4. 写单行代码长度缩短了,敲键盘的速度都变快了