2016-06-13 11 views
0

私はクラスのコレクションを持っています。それはDerived1, Derived2, ..., Derived6と呼ばれ、それぞれが基本クラスBaseのサブクラスです。これらのクラスはサードパーティのJavaパッケージで定義されています。次のOOPデザインにはより良い選択肢がありますか?

私はこれらのオブジェクトの人間が読める表現を書き出すクラスを作成しています。私はこの問題に次のようにアプローチしました。それぞれi=1,2,...,6String transform(Base object)に対してメソッドString transform(Derivedi object)を定義します。

たとえば、Base obj = new Derived3(...)と、objの表現を計算する場合に問題が発生します。式transform(obj)は、 ""のメソッドを呼び出します。このメソッドは、 "正しい"メソッド(この場合は、String transform(Derived3)のシグニチャを持つメソッド)を呼び出す必要があります。

メソッドString transform(Base object)は、それぞれi=1,2,...,6の形式の一連の条件文を使用して適切なメソッドに作用します。if (obj instanceof Derivedi) (私がパッケージをコントロールしていたなら、抽象メソッドString toReadable()をベースクラスに実装する必要があります。残念なことに、この場合、私はパッケージを制御できません)

私はしませんこのソリューションのように(それは簡単に分かります)。 String transform(Base)のこの実装に代わるものは何ですか?

+0

この問題がどのように発生する可能性があるのか​​分かりません。あなたは 'toString()'メソッドをオーバーライドすることを考えましたか?または、あなたが記述したクラス階層内の別の単純な上書き?パラメータを必要とする別の場所の代わりに? – EJP

+0

多型ではありません。多態性は、各クラスにtoHumanRepresentation()メソッドを持たせることで、これは 'this'を人間の表現に変換します。あなたがクラスをコントロールしていない場合は、instanceofのチェックを除いて、あなたができることはあまりありません。 –

+0

これはポリモフィズムではなく、ポリモーフィズムは(toReadable()アプローチのように)すべてのオブジェクトに対して同じメソッドを呼び出すことになります。これにはJavaの仕組みが組み込まれています。すべてのクラスにはObjectから継承されたtoString()メソッドがあり、クラス固有の動作のためにオーバーライドすることができます。そうでない場合は、if-elseシーケンスのような非OOソリューションに頼らなければなりません。あなたがスイッチケースを持っている場合、またはこの場合はその醜いif-elseシーケンスのいとこのたびに、アクションにチェックしている値のマップに置き換えることができます。 –

答えて

1

クラスごとに変圧器(transform(...)を含むオブジェクト)を試すことができます。次に、変圧器をそれらのクラスにマップするマップを維持します(変圧器自体がステートレスであると仮定して)。

例:CDI /リフレクションを使用すると、多少自動的に検索を行うことができることを

class Transformer { 
    Class<? extends Base> getTransformableClass() { ... } 
    String transform(Base obj){ 
    //check and cast obj to the actual type then create the string 
    } 
} 

Map<Class<?>, Transformer> transformers = ...; 
Transformer base = new BaseTransformer(); //the same for derived 
transformers.put(base.getTransformableClass(), base); 

注(すなわち、ルックアップ特定のインターフェースを実装するか、特定のアノテーションを付けされているすべてのクラス)。

次に、このようにそれを使用します。

public String transform(Base obj) { 
    //add null checks etc. 

    return transformers.get(obj.getClass()).transform(obj); 
}  
ジェネリック医薬品は、変圧器を実装していますが、実際に知っていないと思いますので、その後、いくつかのキャスト/生タイプが必要になるだろうマップからそれらを使用する際に役立つかもしれないことを

さらにノートあなたがマップから得るタイプ、すなわちtransformers.get(Derived1.class)Derived1のインスタンスを扱うことができるトランスを返すべきであることをデベロッパーが知っていますが、コンパイラはそのことを知らず、それを適切にキャストする必要があります。

0

getSimpleName()を使用してクラスの名前を取得し、その名前にswitch文を使用できます。この委任はtransform(Base object)で実行する必要がありますが、いくつかのifステートメントとinstanceofのチェックよりも幾分洗練されています。

関連する問題