3

コードが重複している状況があり (またはそうですか?)、それを回避する方法がわかりませんが、コードを明確に保ちます。

状況を非常に単純化しておきます。

// let's say I have a interface Entity

interface Entity {

    public Entity add (Entity operand);

}

// And two classes that implement this interface

class MyInteger implements Entity {

    private int value;

    public Entity add (Entity operand)
    {
         // here I have to manage the situation distinctly if operand is a MyInteger or MyString

    }

}

class MyString implements Entity {

    private String value;

    public Entity add (Entity operand )
    {

    }
}

さて、私の問題は、MyString の add メソッドが MyInteger の add メソッドと基本的に同じであることです。ここで言及した 2 つよりもはるかに多くの型があり、一部のメソッド add は同じではないことに注意してください。

これはコードの重複ですか? もしそうなら、それを避ける方法はありますか?1つも思い浮かばないので。

また、 add メソッドで、 if (instanceof ) ステートメントを使用せずに、オペランドが持つことができるさまざまな型を切り替えるにはどうすればよいですか?

4

4 に答える 4

1

これまでのところ、あなたのアプローチに問題は見られません。

エンティティはインスタンスであるため、次の方法でコードの重複を解決できます。

  • 単純に無視して複製を行うと、クリーンなソリューションが得られます。このような重複が発生するケースが少ない場合は、この方法で実装することをお勧めします。

  • 既に述べたように、すべてのメソッドを保護されたメンバー メソッドとして 1 回実装する AbstractEntity などの抽象クラスを実装し、MyInteger および MyString をサブクラスとして宣言します。

  • サブクラス化をさらに進め、どのエンティティにどのメソッドが必要かを考え、サブクラスのツリーを構築します。注意: 慎重な設計ができないと、これ以上の調整が妨げられます。

  • 必要な機能を実装するには、public static メソッドと private コンストラクターを持つユーティリティ クラス (クラス) を使用します。

エンティティのタイプを調べる方法:

  • instanceof を使用します (わかりました、それは醜いです)
  • 型を Enum として返すインターフェイスにメソッドを実装するか、プロパティをテストします: getType() == STRING または isString()
  • あなたが望むことを行うインターフェースにメソッドを実装してください: checkIfStringAndAddIt()。
于 2012-08-15T10:56:12.430 に答える
1

テンプレートパターンを調べてください。重複するコードの Abstract クラスをリファクタリングして追加できます。これが 2 つのクラスに固有のものである場合は、それら 2 つのクラスだけで Abstract クラスを拡張できます。

回避するinstanceofには何が最適かわかりませんが、必要に応じてスーパー/抽象クラスを呼び出すエンティティクラスに固有の追加のメソッドをチェーンできます。

最後に、ジェネリックによってどのような可能性が提供されるかを調べます。

于 2012-08-15T08:59:10.690 に答える
1

訪問者または二重発送メカニズムが必要なようです。

メソッドadd(Entity operand)は、渡されたオペランドに基づいて何をすべきかを決定する必要があるため、オペランドをコールバックすることでこれを実現できます。例えば

// in MyInteger
public Entity add(Entity operand) {
   operand.addInteger(this);
}

// in MyString
public Entity add(Entity operand) {
   operand.addString(this);
}

上記の実装は、呼び出された型によって変わることに注意してください。オペランドにリダイレクトすることにより、呼び出しパスは、最初に呼び出されたエンティティと使用されたオペランドによって決定されます

各エンティティは などを実装するaddInteger(MyInteger p)必要addString(MyString p)がありますが、この段階では具体的な型があり、何をすべきかを自明に判断できます。

などを使用する必要がないことに注意してくださいinstanceof。上記はタイプセーフで完全です。たとえば、新しいオペランド型を追加すると、明らかな一連のリファクタリングが発生します。

于 2012-08-15T08:59:13.080 に答える
1

抽象クラスを使用して、具体的な add メソッドを提供できます。

于 2012-08-15T08:59:35.717 に答える