类型歧义的设计

时间:2017-12-13 10:29:53

标签: java design-patterns refactoring

在下面的场景中寻找重构建议 我们有一个DataMap<header,RecordHolder> RecordHolder类具有如下近似结构 RecordA,RecordB ....从公共基类型继承 - 记录。

RecordHolder{
    RecordA
    RecordB
    RecordC
    RecordD;

    setRecordA();
    setRecordB();
    ....
}

解析器实用程序读取文件的每一行并转换为相应的记录类型:

Map<key,Record> parse(String line){....}

从parse返回时,将获取与该键对应的RecordHolder实例 - 并且必须调用相应的setRecordXXX方法来更新已解析的记录。

RecordHolder d = DataMap.get(key);
if(d==null){ ==========> (A)
    d = new RecorHolder();
    DataMap.put(key,d);
}
d.setRecordXXX(Record);=========>(B)

问题:
(A)对于地图的get-else-put-and-return来说,这是最好的习语 (B)如果没有Record(RecordA,RecordB等)的显式类型检查,我怎样才能实现这一点

1 个答案:

答案 0 :(得分:3)

  

(A)什么是get-else-put-and-return for map的最佳成语。

您可以使用Map#computeIfAbsent()方法,如下面的代码所示:

DataMap.computeIfAbsent(key, k -> new RecordHolder()).setRecordXXX(Record);

computeIfAbsent将第一个参数作为键,第二个参数作为Function<KeyType, RecordHolder>。因此,当密钥没有值时。然后调用该函数并将其设置为值。

地图中可能的实现可以是以下内容(不是jdk中的实际内容):

public V computeIfAbsent(K key, Function<K,V> mappingFunction){
    V value = this.get(key);
    if(value == null){
        value = mappingFunction.apply(key);
        this.put(key, value);
    }
    return value;
}

类型KV是通用的,分别代表key value的类型。如您所见,方法computeIfAbsent返回value,它位于地图中或稍后创建。然后可以调用setRecordXXX方法。

  

(B)如果没有Record(RecordA,RecordB等)的显式类型检查,我怎样才能实现这一目标

为此你必须在RecordHolder中创建一个方法,它使用if-elseif-else-statement来确定应该设置什么记录。如下所示:

public void setRecordXXX(Record record){
    if(record instanceof RecordA){
        setRecordA((RecordA) record);
    } else if(record instanceof RecordB){
        setRecordB((RecordB) record);        
    } else if(...){
        // other records
    } else {
        // throw when unknown record implementation
        throw new UnsupportedOperation("RecordType not supported: " + record);
    }
}