4

私が開発を支援しているプログラムは、動的に生成されたいくつかの質問を出力して、ユーザーが回答できるようにすることになっています。質問にはさまざまな種類がありConstraint、ユーザーが指定した情報を入力する対応するクラスがあります。私の質問は、さまざまな制約に対して均一な動作を作成する方法です。

                    ---->Constraint<--------------------
                    |                  |               |
                  FConstraint        PConstraint    TConstraint
                  |         |
            UConstraint AConstraint

TConstraint と同様に、基本クラスConstraintは空です。

UConstraintPConstraintおよびAConstraint3 つの変数を共有します。ただし、UConstraint持っていないAConstraint追加の変数が 1 つあります。PConstraint

レンガの壁をハサミで叩こうとしているような気がします。私の考えの 1 つは、署名を使用して Constraint に抽象メソッドを提供することです。

// All answers are of type string.
abstract void setValue(string variable, string answer);

これはすべてのConstraintサブクラスによって実装されます。ただし、設定する変数を決定するために文字列を渡すと、エラーが発生しやすく、同様に悪いコードの匂いがします。

2 番目のオプションは、3 つの同様の変数を Constraint に移動することでしたが、UConstraint, AConstraint設定が必要な追加の情報が残ります。それらのいずれも必要としないことは役に立ちTConstraintません。

私の現在の強引な「このデザインをねじ込む」。解決策はinstanceof、欠落している制約固有の情報を確認して入力するスープです。

Object constraint = item.getConstraint();

if (constraint instanceof AConstraint) {
    AConstraint constraint = (AConstraint) constraint;

    if (constraint.getValue() == null) {
        constraint.setValue(string);
    } else if (constraint.getKey() == null) {
        constraint.setKey(string);
    } // More of the same.
} else if (constraint instanceof PConstraint) {
    // As the above if() group.
} // etc.

この設計には、抽象関数よりも優れたソリューションはありますか?

4

5 に答える 5

3

この原則を使用する

インターフェイスでプログラミングし、変化し続ける動作を抽象クラスまたはインターフェイスでカプセル化します。

例:上記の例の場合

インターフェース - 制約

抽象クラス - FConstraint

具象クラス - PConstraint、TConstraint、UConstraint、AConstraint

于 2012-05-23T18:33:44.230 に答える
3

あなたの質問には、それぞれの場合に必要な実際の作業に関する十分な情報がありませんが、一般的には次のようなコードです:

Object constraint = item.getConstraint();

if (constraint instanceof AConstraint) {
    // Work
} else if (constraint instanceof PConstraint) {
    // Work
} // etc.

ポリモーフィズムを使用して、次のようなものにリファクタリングするのは強いにおいがします。

Constraint constraint = item.getConstraint();
constraint.doWork(...);

特定のクラスは次のようになります。

public class AConstraint {
  public ... doWork(...) {
    if (getValue() == null) {
      setValue(string);
    } else if (getKey() == null) {
      setKey(string);
    } // More of the same.      
  }
}
于 2012-05-23T18:34:37.880 に答える
2

あなたはこのようなことをすることができます:

public interface Constraint{}

public abstract class VariableConstraint implements Constraint 
{ 
  /* hold 3 shared variables here */
}

public class UConstraint extends VariableConstraint{}
public class PConstraint extends VariableConstraint{}
public class AConstraint extends VariableConstraint{}

public abstract class EmptyConstraint implements Constraint {}

public class TConstraint extends EmptyConstraint {}
于 2012-05-23T18:19:28.107 に答える
1

共通の機能を指定します:オブジェクト(実際にはサブタイプの1つのオブジェクトである可能性があります)Constraintに対して実行できるようにする操作には、サブクラスでオーバーライドするという点でその機能のメソッドがあります。ConstraintConstraint

その機能が意味をなさない親クラスに対して、些細な(たとえば空の)実装を行うことができます。

このように、オブジェクトの具体的なクラスを気にする必要はありません。スーパークラスが提供する機能を使用するだけです。

于 2012-05-23T18:19:15.377 に答える
1

Constraintインターフェイスとして使用します。これを拡張する抽象クラスを定義Constraintします。これには共有変数が必要です。UConstraintAConstraint共有変数を持つこの抽象クラスを拡張する必要があります。残りのクラスは、インターフェイスを直接実装できConstraintます。コードのインスタンスは次のように変更する必要があります

Constraint constraint = item.getConstraint();
constraint.doWork(..);

常に優れた設計は、インターフェイスに対してコードを記述することです

于 2012-05-23T18:26:24.840 に答える