返回多个枚举值的最佳方法是什么? (Java 和 C#)
删除了更多原始内容,以使问题更容易参考:
所以我有一个 House
类,它有一个方法 House.buy(Person p)< /code>,导致该人购买房子。我想知道这个人是否可以购买房子,所以我还有一个方法
House.tryBuy(Player p)
来返回这个人是否可以购买房子。我有一个枚举 BuyState
,其值包括 OK
、NotEnoughMoney
和 AlreadyOwned
。有几个不同的条件需要满足,客户想知道哪个条件失败了。但如果多个条件都不成立怎么办?我可以有一个层次结构,例如,如果 House 已被拥有并且 Person 没有足够的钱,则返回 BuyStates.AlreadyOwned
。但这只能让我告诉客户一件事。
我可以有 N 个单独的条件和一个具有 N*N 值的枚举,例如 ConditionA_AND_ConditionB_ANDConditionC
但这根本没有意义,原因有几个。我知道有位字段,每个条件都有一个位,但它们看起来级别太低,实现起来很烦人,而且不可扩展。所以我需要一种方法从枚举返回值列表,那么像这样的类怎么样:
class C<type_of_enum> {
private List<type_of_enum> values;
//etc etc
}
这是“最佳”可能的设计吗?
(保留有关 java 和 C# 的问题以保持答案有效)
more of original content deleted to make question easier to reference:
So I have a House
class that has a method House.buy(Person p)
, causing the person to buy the house. I want to know if its possible for the Person to buy the House, so I also have a method House.tryBuy(Player p)
that returns if the Person can buy the house. I have an enum BuyState
with values like OK
, NotEnoughMoney
, and AlreadyOwned
. There's a few different conditions to be satisfied, and the client would like to know which failed. But what if multiple conditions fail? I could either have a hierarchy, like if House is already owned and Person doesn't have enough money, return BuyStates.AlreadyOwned
. But this only lets me tell the client one thing.
I could have N separate conditions and an enum with N*N values, like ConditionA_AND_ConditionB_ANDConditionC
but that makes no sense at all for several reasons. I know there are bit-fields, with a bit for each condition, but they just seem too low-level, annoying to implement, and not-scalable. So I need a way to return a list of values from an enum, So how about a class like this:
class C<type_of_enum> {
private List<type_of_enum> values;
//etc etc
}
Is this the "best" possible design?
(keeping this question about java AND C# to keep answers valid)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
对我来说听起来不错。您想要返回失败条件的列表,并且您正在返回失败条件的列表。
It sounds fine to me. You want to return a list of the conditions that failed, and you're returning a list of the conditions that failed.
您可以使用回调:
You could use a callback:
您可以将列表指针传递给函数,而不是返回列表,以便在出现错误情况时填写原因。该函数本身可以返回 0 表示成功,返回 1 表示失败,在这种情况下您可以检查列表的内容。
这将使您更快地知道函数调用是否成功(假设大多数情况下都会成功)。
Instead of returning a list, you can pass a list pointer to the function, to be filled up with reasons in case error conditions arise. The function itself can return 0 to indicate success and 1 for failure, in which case you can check the content of the list.
This will make it faster to know if the function call was successful or not, assuming most of the time it will be success.
在 Java 中,最自然的方法是使用 <代码>EnumSet。构建一个的示例:
In Java, the most natural way to do this is with
EnumSet
. An example of constructing one:在 C# 中,我会使用标志枚举。
检查设计标志枚举。
In C# I would go for a flags enumeration.
Check Designing Flags Enumerations.
这似乎是一个奇怪的设计。当用软件对现实世界的事物进行建模时,让模型反映现实是有好处的;这样的模型更容易理解、维护和扩展。
首先,房子不是买人的东西。人就是买房子的东西。 “买”的方式应该是在“人”上,而不是在“房子”上。
其次,房子并不是决定买不买房的因素。房屋的所有者是决定房屋是否可以购买的实体。 (为什么会出现“已拥有”错误条件?当然,房子已经被拥有了。有人拥有它。)
第三,您可能必须考虑在多个买家可能尝试的世界中会发生什么一次性买下房子。实际上,卖方收集各种报价并进行还价,销售可能取决于其他事件,等等。所有这些东西都应该出现在模型中吗?如果是的话,在哪里?可能处于代表所有者的对象的状态,因为所有者是正在与之协商的对象。
第四,现实中,购房交易通常涉及受信任的第三方进行托管,以及可能提供资金或持有留置权的卖方和买方贷款人等各种其他方。这些参与方是否反映在该模型中?
第五,如果你的目的是在你的模型中添加“你不能买这栋房子的原因”,那么你所描述的是一个政策体系。在这种情况下,请将策略表示为系统中的一流对象,以便可以像任何其他对象一样操作它们。业主有关于在什么条件下出售的政策。银行有关于贷款条件的政策。等等。
在这个模型中,您的问题变成“询问政策解决引擎,买方是否满足每个相关机构的政策树所施加的所有必要条件,以便购买给定的房屋”。换句话说,问题是“X可以购买Y吗?”不是由 X 或 Y 来计算的;这是一个需要政策解决引擎来解决的问题,而这个问题就是给你返回一份 X 未能履行的政策列表,以便从 Z 购买 Y。
有意义吗?
This seems like a bizarre design all around. When modeling real-world things in software, it pays dividends to make the model reflect reality; such models are easier to understand, maintain, and expand.
First off, a house is not something that buys a person. A person is something that buys a house. The "buy" method should be on "person", not on "house".
Second, a house is not something which determines whether a house can be bought. The owner of the house is the entity which determines whether it can be bought. (Why is there an "already owned" error condition? Of course the house is already owned. Someone owns it.)
Third, you might have to consider what happens in a world where multiple buyers might be attempting to buy the house all at once. In reality, the seller collects various offers and makes counteroffers, sales may be contingent upon other events, and so on. Should all of those things be present in the model? If so, where? Probably in the state of the object representing the owner, since the owner is the thing being negotiated with.
Fourth, in reality, house purchasing transactions usually involve a trusted third party to do escrow, and various other parties such as the seller's and buyer's lenders who might be providing funds or holding liens. Are those parties reflected in this model?
Fifth, if your intention is to add to your model "reasons why you cannot buy this house", then what you are describing is a policy system. In that case, represent policies as first-class objects in your system, so that they can be manipulated like any other objects. Owners have policies about under what conditions they will sell. Banks have policies about the conditions under which they will lend. And so on.
In this model, your problem becomes "ask the policy resolution engine if the buyer meets all the necessary conditions imposed by every relevant agency's policy trees in order to purchase a given house". In other words, the question "can X buy Y?" is not for either X or Y to figure out; it's a matter for a policy resolution engine to work out, and THAT thing is what gives you back a list of the policies X has failed to fulfill in order to purchase Y from Z.
Make sense?
是的,这看起来确实是最好的设计。您想要返回一个(或一组)原因列表,因此很自然地将其作为一组返回。
Yes, that does seem like the best design. You want to return a list (or set) of reasons, so it's natural to return it as a set.
我认为返回一份不购买的理由清单很好;它非常能表达你想要做的事情。一套可能更合适,但也只是稍微合适一点。
I think returning a list of reasons not to buy is great; it's very expressive of what you're trying to do. A set would probably be more appropriate, but only slightly so.