0

質問を参照しやすくするために削除された元のコンテンツの多く:

そのHouseため、メソッドを持つクラスがあり、House.buy(Person p)その人に家を購入させます。Person が House を購入できるかどうかを知りたいのでHouse.tryBuy(Player p)、Person が家を購入できるかどうかを返すメソッドもあります。、、、などのBuyState値を持つ列挙型があります。満たすべきいくつかの異なる条件があり、クライアントはどれが失敗したかを知りたがっています。しかし、複数の条件が失敗した場合はどうなるでしょうか? House がすでに所有されていて、 Person が十分なお金を持っていない場合のように、階層を持つこともできます。しかし、これでクライアントに言えることは 1 つだけです。OKNotEnoughMoneyAlreadyOwnedBuyStates.AlreadyOwned

N 個の個別の条件と N*N 値を持つ列挙型を使用できますがConditionA_AND_ConditionB_ANDConditionC、いくつかの理由でまったく意味がありません。条件ごとにビットフィールドがあることは知っていますが、それらはあまりにも低レベルで、実装するのが面倒で、スケーラブルではないようです。したがって、列挙型から値のリストを返す方法が必要です。では、次のようなクラスはどうでしょうか。

class C<type_of_enum> {
    private List<type_of_enum> values;

    //etc etc
}

これは可能な限り「最高の」設計ですか?

(回答を有効に保つために、Java AND C#に関するこの質問を維持してください)

4

8 に答える 8

12

Javaでは、これを行う最も自然な方法はを使用することですEnumSet。1つを構築する例:

return EnumSet.of(BuyConditions.NotEnoughMoney, BuyConditions.AlreadyOwned);
于 2009-11-17T22:46:08.437 に答える
8

C#では、フラグの列挙を行います。

DesigningFlagsEnumerationsを確認してください。

于 2009-11-17T22:45:15.603 に答える
7

これは「最良の」可能な設計ですか?

これはいたるところに奇妙なデザインのようです。ソフトウェアで現実世界のものをモデル化するとき、モデルに現実を反映させるために配当を支払います。このようなモデルは、理解、保守、および拡張が容易です。

まず第一に、家は人を買うものではありません。人は家を買うものです。「購入」方法は、「家」ではなく「人」で行う必要があります。

第二に、家は家を買うことができるかどうかを決定するものではありません。家の所有者は、それを購入できるかどうかを決定するエンティティです。(「すでに所有されている」エラー状態があるのはなぜですか?もちろん、家はすでに所有されています。誰かが所有しています。)

第三に、複数の購入者が一度に家を購入しようとしている可能性がある世界で何が起こるかを考慮する必要があるかもしれません。実際には、売り手はさまざまなオファーを収集してカウンターオファーを作成し、販売は他のイベントに依存する場合があります。それらすべてがモデルに存在する必要がありますか?もしそうなら、どこ?所有者は交渉対象であるため、おそらく所有者を表すオブジェクトの状態にあります。

第4に、実際には、住宅購入取引には通常、信頼できる第三者がエスクローを行うことや、資金を提供したり先取特権を保有したりする可能性のある売り手や買い手の貸し手など、さまざまな他の当事者が関与します。それらの関係者はこのモデルに反映されていますか?

第五に、あなたの意図があなたのモデルに「あなたがこの家を買うことができない理由」を加えることであるならば、あなたが説明しているのは政策システムです。その場合、ポリシーをシステム内のファーストクラスのオブジェクトとして表現し、他のオブジェクトと同じように操作できるようにします。所有者は、どのような条件で販売するかについての方針を持っています。銀行には、貸し出す条件についての方針があります。等々。

このモデルでは、問題は「購入者が特定の家を購入するために、関連するすべての機関のポリシーツリーによって課せられるすべての必要条件を満たしているかどうかをポリシー解決エンジンに尋ねる」になります。言い換えれば、「XはYを買うことができるか」という質問です。XまたはYのどちらも理解するためのものではありません。ポリシー解決エンジンが機能するかどうかは問題です。それが、ZからYを購入するためにXが実行できなかったポリシーのリストを返すものです。

わかる?

于 2009-11-17T23:27:25.457 に答える
1

はい、それは最高のデザインのようです。理由のリスト(またはセット)を返したいので、セットとして返すのが自然です。

于 2009-11-17T22:42:33.073 に答える
1

購入しない理由のリストを返すのは素晴らしいことだと思います。それはあなたがやろうとしていることを非常に表現しています。セットの方がおそらく適切ですが、ほんの少しだけです。

于 2009-11-17T22:42:41.693 に答える
0

それは私にはうまく聞こえます。失敗した条件のリストを返したいのですが、失敗した条件のリストを返しています。

于 2009-11-17T22:42:18.033 に答える
0

コールバックを使用できます:

class House {

    public void buy(Result result) {

        if (true)
            result.ok(this);
        else
            result.error(this, EnumSet.of(Status.NOT_ENOUGH_MONEY, Status.ALREADY_OWNED));

    }

}

enum Status {

    NOT_ENOUGH_MONEY,
    ALREADY_OWNED

}

interface Result {

    public void ok(House house);

    public void error(House house, EnumSet<Status> status);

}
于 2009-11-17T22:46:35.960 に答える
0

リストを返す代わりに、リスト ポインターを関数に渡して、エラー状態が発生した場合に理由を入力することができます。関数自体は、成功を示す場合は 0 を返し、失敗を示す場合は 1 を返すことができます。この場合、リストの内容を確認できます。

これにより、ほとんどの場合は成功すると仮定して、関数呼び出しが成功したかどうかをより速く知ることができます。

于 2009-11-17T22:51:25.390 に答える