5

私はいくつかのコード (Java) を見直し、ビジネス ロジック フロー チャートに基づいて変更を加えています。現在のコードは、大量の if ステートメントに依存しています。これを避けたいと考えています。私はポリモーフィズムについて読んでいて、それを自分の状況に適用する方法に頭を悩ませようとしています。単一レベルの条件付きで機能させることはできますが、複数の条件付きレベルにさらに拡張するのに苦労しています。コードは実行時に実行され、この「ロジック」メソッドには前のステップから変数が渡されます。

不自然な例: 2 つの動物園、「動物園 A」と「動物園 B」、および「ホーム」があります。これらのそれぞれが「場所」です。各動物園には、「北」、「南」、「東」、「西」の 4 つの「場所」があります。「ホーム」には 1 つの場所しかありません。いくつかの変数に基づいて、どこに行くべきかについて「目的地」を人に割り当てたいと考えています。これらの変数は次のとおりです。「場所」は、場所 (動物園 A、動物園 B、ホーム) に関連付けられます。私たちの場所に関連する「方向」(北、南、東、西)。フローチャート:

                |----- | 'HOME'
                |Place?| ----- >  *destination = 'home'*
                |----- |
     Zoo A          |                               Zoo B
    |---------------|----------------------------------------|
|----------|                                        |----------| 
|Direction?|                                        |Direction?| 
|----------|                                        |----------|
    |    North                                          |    North
    ----------- *destination = 'Zoo A North'            ----------- *destination = 'Zoo B North'
    |    East                                           |    East
    ----------- *destination = 'Zoo A East'             ----------- *destination = 'Zoo B East'
    |    South                                          |    South
    ----------- *destination = 'Zoo A South'            ----------- *destination = 'Zoo B South'
    |    West                                           |    West
    ----------- *destination = 'Zoo A West'             ----------- *destination = 'Zoo B West'

したがって、人物 X の場所が動物園 A で方向が南である場合、目的地は「動物園 A 南」である必要があります。

If ステートメントを使用して、現在かなり醜いコードがあります。

if(Place = 'HOME')
    destination = 'HOME'
if(Place = 'Zoo A')
    if(Direction = North)
        destination = 'Zoo A North')
    if(Direct = East)
        destination = 'Zoo A East')
    ...
if(Place = 'Zoo B')
    if(Direction = North)
        destination = 'Zoo B North')
    if(Direct = East)
        destination = 'Zoo B East')
    ...

これを、変数を ENUM としてネストされたスイッチに変換できます。しかし、私はそれに陥る悪い癖があるので、if - else / switch への依存を避けようとしています。Factory Design を使用して Place クラスを生成する実験を行い、次に各場所と目的地でポリモーフィズムを使用しましたが、頭の中で複雑になりすぎました。if/switchs から離れる価値はありますか? 私はそれをオーバーエンジニアリングしようとしているだけですか?

このようなロジック フローに取り組む方法について何か提案はありますか? ありがとう

4

8 に答える 8

3

これは次のようにモデル化できます。

  1. Placeメソッドでルートクラスを使用しcalculateDestination(Person)ます。場所は、その中の他の場所で構成できます。
  2. andPlaceのサブクラスを作成します(これらは実際の場所であるため、当然のことです)。ZooZooQuadrant
  3. Personオブジェクトにはとの値がcurrentPlaceありますcurrentDirection

これらのクラスのオブジェクトをインスタンス化して、状況を表現します。

zooA = new Zoo("ZooA");
zooA.addChild(new ZooQuadrant(Direction.SOUTH));
... so on for every quadrant ...
... same for zooB ...
home = new Place("Home");
world = new Place("World");
world.addChild(home);
world.addChild(zooA);
world.addChild(zooB);

目的地を取得したいときは、電話しますworld.calculateDestination(myPerson)

calculateDestination(Person)ポリモーフィックメソッドです。継承階層の各レベルは、そのクラスの特定のセマンティクスに従ってそれをオーバーライドします。

  1. PlacePersonには、インスタンスが現在そのノードにあるかどうかをテストする一般的な実装があり(Personの の値に対してテストすることによってcurrentPlace)、そうでない場合は、それぞれの子を呼び出しcalculateDestinationてそれを返します。
  2. Zoos は をチェックする必要がありcurrentPlace == this、そうである場合は、各象限を呼び出しcalculateDestination、肯定的な結果を独自の結果と組み合わせて を返しthis.name + quadrantResultます。
  3. それぞれが、それ自体の方向と等しいZooQuadrantかどうかを確認し、それに応じて値を返す必要があるだけです。currentDirection

注: これはポリモーフィズムがどのように機能するかを説明するためのものであり、より良い実装があるかもしれません。また、ここではポリモーフィズムと再帰の両方を使用していますが、この 2 つは独立しています。


編集:

追加された複雑さが保証されるかどうかに関しては、それは依存します! ここでは、非常に小さいオブジェクト グラフを使用した単純な例を使用しています。数十の動物園があり、それらの動物園にさらに象限を追加する必要がある場合、または追加レベルの決定を行う必要がある場合 (たとえば、各象限にサブ象限がある場合)、ネストされた if-else-if メソッド (手続き型) が実際に取得されます。オブジェクト指向のアプローチは維持可能で理解しやすいままですが。

すべてのことと同様に、意思決定が複雑になることが予測される場合は、OO アプローチを使用してください。それ以外の場合は、常にシンプルに保つことが美しさよりも優先されます。適切な問題には適切なツールを使用してください。

于 2013-01-10T01:36:30.150 に答える
0

このことから、必要な少なくとも 3 つのクラスが Place、Direction、Destination であることがわかります。

Place には name プロパティと getName() メソッドがあり、名前は Zoo A、Zoo B、Home に設定されます。

動作が異なる場合は、Place の Home および Zoo サブクラスを作成します。この例では、Home には方向がありませんが、Zoo には方向があるため、それを行うことができます。

方向は、North、East、West、South を含む列挙型 (特別なタイプのクラス) にすることができます。

Destination には、Place と Direction という 2 つのプロパティがあります。メソッド getDestination() もある

public String getDestination(){
    if (this.direction == null){
        result = this.place.getName();
    } else {
        result = this.place.getName() + " " + this.direction.getName();
    }
    return result;
}
于 2013-01-10T01:06:38.743 に答える
0

1 つのアプローチは、メソッド getNorthDestination()、getEastDestination() などを使用して、親 asbtract クラス/インターフェイス 'Place' を作成することです。

次に、「ZooA」と「ZooB」という「Place」のサブクラス/実装を作成し、対応する場所を返す getXXXDestination() メソッドをオーバーライド/実装します。

于 2013-01-10T00:58:27.357 に答える
0

ゲリータンの答えに行きます。すべての情報について、「これには本当にクラスが必要なのか?」と自問する必要があります。多くの場合、答えはノーです。単純な文字列/数値変数で十分です。ここで、パブリック変数 (C++ など) を直接参照するのではなく、これらの変数をゲッター/セッター メソッドと結合する必要があります。これは、Java が重視していることです。たとえば、単純なメソッドを参照することは、テストするよりもはるかに簡単です。

于 2013-01-10T01:08:49.203 に答える
0

Zoo A と Zoo B を含む新しいメソッドを作成できます...... directionForZoo() のように呼び出すことができ、while ループを使用してみると、

于 2013-01-10T01:17:31.800 に答える
0

過度に設計したくない場合は、次の回避策が if/else を取り除く簡単な解決策になります。しかし、それはエレガントなアプローチではありません。

キーが (場所 + 方向) で、値が対応する目的地であるマップを作成できます。これは、Place と Direction の値がプログラムで現在静的に近く、あまり変化しない場合にのみ問題ありません。

例: 場所と対応する目的地を地図に保存する

Map<String, String> destMap = new HashMap<String, String>();
destMap.put("HOME","HOME");
destMap.put("Zoo A+North","Zoo A North");
destMap.put("Zoo A+East","Zoo A East");
destMap.put("Zoo B+North","Zoo B North");

場所と方向に従って目的地を取得する:

destMap.get(Place + "+" + Direction);
于 2013-01-10T05:27:12.313 に答える
0

あなたの例に対する1つの可能な解決策は、(おそらく抽象)Locationクラスを作成することです。これには、宛先のデータ構造を含めることができます。このデータ構造の 1 つの可能性は、おそらく a Map<Direction, Location>) であり、その方向に進むための宛先であるオブジェクトにDirectionマップするキーとして使用できる列挙型です。Locationサブクラス化して 、 などのクラスを作成するか、異なる を区別するフィールドを提供Locationできます。または、これらの両方を組み合わせて行うこともできます。HomeZoonameLocation

これは中途半端な設計であり、必要に応じて役立つ場合とそうでない場合があることに注意してください。優れた OO 設計には、解決しようとしている問題の正確な要件に関する経験と詳細な知識が必要です。私は前者のいくつかを持っていますが、後者についてはほとんど理解していません。

于 2013-01-10T17:32:44.450 に答える
0

いくつかの提案された回答のバリエーションを試しました。

ネストされたスイッチケースブロックを使用することになりました。最も理想的ではなく、私が避けたかったことではありませんが、私の目的のためには、より保守が容易です (変更も拡張もされません)。

私のバージョンのこれは非常にうまく機能したので、@Ezequiel Munsメソッドを正しいものとしてマークします-それは問題に必要なものではありません。

すべての助けをありがとう。

于 2013-01-16T08:38:42.663 に答える