0

删除了更多原始内容以使问题更易于参考:

所以我有一个House类有一个方法House.buy(Person p),导致人买房子。我想知道这个人是否有可能买房子,所以我也有一个方法House.tryBuy(Player p),如果这个人可以买房子,我就会返回。我有一个枚举BuyState值,如OK,NotEnoughMoneyAlreadyOwned. 有几个不同的条件需要满足,客户想知道哪个失败了。但是如果多个条件都失败了怎么办?我可以有一个层次结构,比如如果 House 已经拥有并且 Person 没有足够的钱,则 return BuyStates.AlreadyOwned。但这只能让我告诉客户一件事。

我可以有 N 个单独的条件和一个具有 N*N 值的枚举,ConditionA_AND_ConditionB_ANDConditionC但是由于几个原因,这根本没有意义。我知道有位域,每个条件都有一个位域,但它们看起来太低级了,实现起来很烦人,而且不可扩展。所以我需要一种从枚举中返回值列表的方法,那么这样的类怎么样:

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

    //etc etc
}

这是“最好”的设计吗?

(保持这个关于 java 和 C# 的问题以保持答案有效)

4

8 回答 8

12

在 Java 中,最自然的方法是使用EnumSet. 构建一个示例:

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

在 C# 中,我会使用标志枚举。

检查设计标志枚举

于 2009-11-17T22:45:15.603 回答
7

这是“最好”的设计吗?

这似乎是一个奇怪的设计。在软件中对现实世界的事物进行建模时,使模型反映现实是有好处的;这样的模型更容易理解、维护和扩展。

首先,房子不是买人的东西。人就是买房子的东西。“购买”方法应该在“人”上,而不是在“房子”上。

第二,房子不是决定房子能不能买的东西。房屋的所有者是决定是否可以购买的实体。(为什么会出现“已经拥有”的错误情况?当然房子已经拥有了。有人拥有它。)

第三,您可能必须考虑在多个买家可能试图同时购买房屋的世界中会发生什么。实际上,卖方收集各种报价并进行还价,销售可能取决于其他事件,等等。所有这些东西都应该出现在模型中吗?如果有,在哪里?可能处于代表所有者的对象的状态,因为所有者是正在与之协商的事物。

第四,实际上,购房交易通常涉及受信任的第三方进行托管,以及可能提供资金或持有留置权的卖方和买方的贷方等各种其他方。这些各方是否反映在这个模型中?

第五,如果你的意图是在你的模型中添加“你不能买这房子的原因”,那么你描述的是一个政策体系。在这种情况下,将策略表示为系统中的第一类对象,以便可以像任何其他对象一样操作它们。业主有关于在什么条件下出售的政策。银行有关于他们将在何种条件下放贷的政策。等等。

在这个模型中,您的问题变成“询问政策解决引擎,如果买方满足每个相关机构的政策树为购买给定房屋而施加的所有必要条件”。换句话说,“X能买Y吗?”这个问题。不是 X 或 Y 都可以计算出来的;政策解决引擎要解决问题,这就是让您返回 X 未能履行的政策列表的原因,以便从 Z 购买 Y。

说得通?

于 2009-11-17T23:27:25.457 回答
1

是的,这似乎是最好的设计。您想返回一个(或一组)原因列表,因此将其作为一组返回是很自然的。

于 2009-11-17T22:42:33.073 回答
1

我认为返回一份不购买的理由清单很棒;它非常能表达你想要做什么。一套可能更合适,但只是稍微合适。

于 2009-11-17T22:42:41.693 回答
0

您可以将列表指针传递给函数,而不是返回列表,以便在出现错误情况时填写原因。函数本身可以返回 0 表示成功,返回 1 表示失败,在这种情况下您可以检查列表的内容。

假设大多数时候它会成功,这将更快地知道函数调用是否成功。

于 2009-11-17T22:51:25.390 回答
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 回答