私は、例の私の質問を説明します。
私は2つのクラスを持っているNumberGeneratorApple
とNumberGeneratorOrange
。それらの両方が同じシグネチャと戻り値の型とメソッドを持っていますpublic Integer getNumber()
。問題は、それが論理的だろうalthought彼らは同じインターフェイスを実装していないです。私はこの方法でインタフェースを作成し、それを実装するために、これらのクラスを変更するが、私はそうする必要はありませんでした。ここではその理由です。これらのクラスは、みましょうと言うのXMLから自動的に生成されます。実際の例では、このようなクラスの数十があります。当社は随時、それらを生成する必要があり、それは古いものを上書きします。私は、それぞれの世代の後にインターフェイスを実装するために、手動で各クラスを変更する必要はありません。また、それはいくつかの時間後に同じプロジェクトに取り組んでいくつか他の人のためにも私のために行われるべきであることは明らかではないかもしれません。
ここで最初のクラスは、次のとおりです。
public class NumberGeneratorApple {
public Integer getNumber(){
return 9;
}
}
2つ目:
public class NumberGeneratorOrange {
public Integer getNumber(){
return 19;
}
}
Althoughtは、彼らは私が一般的な方法でそれらを使用する必要が同じインターフェイスを実装していません。私はちょうどこのような何かをしたいです:
public class ClassThatOperates<T extends NumberGeneratorInterface> {
T generator;
public ClassThatOperates(T generator) {
this.generator = generator;
}
public void doSomeOperation(){
//Obviously it won't work for NumberGeneratorApple and NumberGeneratorOrange
// because they do not implement NumberGeneratorInterface
//And if I change "<T extends NumberGeneratorInterface>" to "<T>"
// I cannot write method call "generator.getNumber()"
System.out.print("The number with constant is: ");
System.out.println(generator.getNumber() + 5);
}
}
これは、(私は公衆が必要ありません知っている、それはデフォルトであり、私はちょうどそれを強調したい)インタフェースです。
public interface NumberGeneratorInterface {
public Integer getNumber();
}
あなたが見ることができるようにあるため、どちらも、このようなことを行うことは不可能ではないNumberGeneratorApple
にもNumberGeneratorOrange
実装NumberGeneratorInterface
。しかし、私はいくつかの解決策を考え出したが、私の本能以下の私はそれがかなり貧弱だと思います。私はラッパークラスを作りました:
public class NumberGeneratorAppleWrapper extends NumberGeneratorApple implements NumberGeneratorInterface {
}
そして
public class NumberGeneratorOrangeWrapper extends NumberGeneratorOrange implements NumberGeneratorInterface {
}
それは少しトリッキーです。あなたははgetNumber(呼び出すときにそれはあなたが実際にこのような何かを呼び出し、このクラスのいずれかのオブジェクトに)最初は明白ではないことかもしれませんが。
@Override
public Integer getNumber() {
return super.getNumber();
}
今、私はこのようにそれを呼び出すことができます。
public class Main {
public static void main(String[] args) {
ClassThatOperates<NumberGeneratorAppleWrapper> classThatOperatesApple = new ClassThatOperates<>(new NumberGeneratorAppleWrapper());
ClassThatOperates<NumberGeneratorOrangeWrapper> classThatOperatesOrange = new ClassThatOperates<>(new NumberGeneratorOrangeWrapper());
classThatOperatesApple.doSomeOperation();
classThatOperatesOrange.doSomeOperation();
}
}
そして、私は次のような出力が得られます。
The number with constant is: 14
The number with constant is: 24
このようなアプローチの利点はなく、手動で追加するimplements NumberGeneratorInterface
各生成されたクラスには、我々は(古いクラスを上書きします)各世代の後に同じ作業を繰り返す必要がないということです。私たちは、新しいラッパーを追加する必要がある場合、いくつかの新しい、追加のクラスの生成結果。
私は、このようなシナリオでは私はジェネリックを取り除くことができることを知っているClassThatOperates
だけに宣言NumberGeneratorInterface generator;
せずに<T extends...>
コードを単純になるので、そのために(と私も必要があります)が、私はいくつかの実際のプロジェクトで見つかったものに、この例では、非常に似て作りたいです。私が書いた:私は、私が作った、私がアップなどに来たが、実際にそれは私はいくつかのプロジェクトで見つかったことを、すでに既存のコードに基づいています。
私の質問があります:
1。よりよい解決策はありますか?
2.このソリューションは、いわゆる「悪趣味」となっていますか?
私はこのようなソリューションを使用する必要がある場合3.多分私の全体のアプローチが間違っていますか?
4.全体的なアプローチは、(ジェネリック医薬品の退治を含む)は、このコードを向上させることができるものが間違っていても何もよりよい解決策がない場合は?
- よりよい解決策はありますか?
あなたのソリューションは、私にはよさそうです。あなたは、使用しているAdapterパターンそれ以外の場合は無関係なインタフェースに適合するために既存の機能を使用しています、。変更することなく、NumberGeneratorApple
そしてNumberGeneratorOrange
、あなたはそれらのクラス機能をするようになってきましたNumberGeneratorInterface
。
あなたが持っていた場合より一般的に、あなたは異なるシグネチャを持つ既存の方法は、例えば、インタフェースに適合させることができています
public class NumberGeneratorApple {
public Integer getAppleNumber(){
return 9;
}
}
次に、あなたのアダプタクラスを明示的に呼ぶようなgetAppleNumber
インターフェイスを実装する場合。
public class NumberGeneratorAppleWrapper extends NumberGeneratorApple implements NumberGeneratorInterface {
@Override
public Integer getNumber() {
return getAppleNumber();
}
}
- このソリューションは、いわゆる「悪趣味」となっていますか?
このソリューションには悪趣味を残しません。Adapterパターンは、十分に確立されたデザインパターンです。
- 私はこのようなソリューションを使用する必要がある場合は、多分私の全体のアプローチが間違っていますか?
次のような既存のクラスを変更できない場合NumberGeneratorApple
は、Adapterパターンは、移動するための方法です。あなたがそれらを変更することができた場合は、ちょうどクラスは、直接必要なインターフェイスを実装しています。
public class NumberGeneratorApple implements NumberGeneratorInterface {
@Override
public Integer getNumber() {
return 9;
}
}
または、メソッドのシグネチャが異なる場合:
public class NumberGeneratorApple implements NumberGeneratorInterface {
public Integer getAppleNumber() {
return 9;
}
@Override
public Integer getNumber() {
return getAppleNumber();
}
}
- 全体的なアプローチが間違っていても何のよりよい解決策がない場合、何が(ジェネリック医薬品の退治を含む)このコードでは改善されるだろうか?
あなたのクラスは以下のような場合はNumberGeneratorApple
本当に正確に一つの方法を持っており、この質問の目的のために複数の方法で、より複雑なクラスだけの単純化されない別の答えを示唆しているとして、あなたはメソッドの参照を使用することができます。代わりに、独自のインタフェースを宣言するNumberGeneratorInterface
、メソッド参照は、として入力することができますSupplier<Integer>
。
public class ClassThatOperates {
Supplier<Integer> generator;
public ClassThatOperates(Supplier<Integer> generator) {
this.generator = generator;
}
public void doSomeOperation(){
System.out.print("The number with constant is: ");
System.out.println(generator.get() + 5);
}
}
そして、あなたはそれをとして使用することができます。
NumberGeneratorOrange ngo = new NumberGeneratorOrange();
ClassThatOperates cto = new ClassThatOperates(ngo::getNumber);
cto.doSomeOperation();