2017-12-13 23 views
-1

下記のシナリオでリファクタリングの提案を探しています。
私たちはDataMap<header,RecordHolder>です。
RecordHolderクラスの構造は、次のとおりです。
RecordA、RecordBは共通基底型から継承しています。タイプ曖昧さのためのデザイン

RecordHolder{ 
    RecordA 
    RecordB 
    RecordC 
    RecordD; 

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

パーサユーティリティは、ファイルの各行を読み取り、対応するレコード・タイプに変換:解析から戻った

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

、キーに対応するRecordHolderインスタンスがフェッチされるべきであり - そして解析されたレコードを更新するには、適切なsetRecordXXXメソッドを呼び出す必要があります。で

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

質問:
(A)をいただきました!マップの取得、他の-入れ-とリターンのための最高のイディオム。
私はレコード(RECORDA、RecordBなどなど)の明示的な型チェックせずにこれを達成することができますどのように(B)

+0

レコードがすべてRecordクラスから継承されている場合、RecordHolderは各サブクラスの可能なインスタンスではなく単一のレコードメンバーを持っていないのはなぜですか? –

+0

setRecordA()、setRecordB()は実際に何をしますか? RecordA/RecordBメンバーにレコードを割り当てるだけですか?または、それぞれの異なるレコードタイプに固有のロジックがありますか? –

+0

各ホルダーオブジェクトには、レガシーからのメソッドsetRecordXXXのバリエーションを考慮した、各タイプのレコードが含まれます。 – IUnknown

答えて

3

(A)をいただきました!マップの取得、他の-入れ-とリターンのための最高のイディオム。

次のコードのようにあなたは、Map#computeIfAbsent()方法を利用することができます:

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

computeIfAbsentは、最初の引数として鍵を受け取り、第二引数Function<KeyType, RecordHolder>として。したがって、キーの値が存在しないとき。その後、関数が呼び出され、値として設定されます。

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はジェネリックであり、それぞれkeyvalueの種類を表す:

は、マップ内の可能な実装は、(ただし、JDKから実際のない)、次のことができます。ご覧のように、メソッドcomputeIfAbsentvalueを返します。これはマップ内にあるか、後で作成されたものです。その上でsetRecordXXXメソッドを呼び出すことができます。

私はあなたがif-elseif-else-statementを使用していますRecordHolderでメソッドを作成する必要があるだろうというのレコード(RECORDA、RecordBなどなど)

の明示的な型チェックせずにこれを達成することができますどのように(B)どのレコードを設定すべきかを決定する。

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); 
    } 
}