问题
In C I've done this sort of thing
enum { USE_COKE = 1,
USE_PEPSI = 2,
USE_JUICE = 4,
USE_WATER = 8 };
int makeDrink(int flags);
//...
int rcode = makeDrink(USE_COKE | USE_JUICE | USE_WATER);
I know this is pretty standard, it's also used in iostream
for instance. I'm wondering how to translate this design pattern into Java or OOP? I'm pretty sure polymorphism is not the way to go here since it'd be better for my code to have an if(flag_is_set)
block than rewrite much of the routine. Is there a utility Flags
class, or a preferred way to do this using a configuration object, or an enum
, or a bunch of ints, etc.
回答1:
Java has enumerations. Here's the tutorial.
I would use these over ints etc. It's a type-safe solution, and since enums are objects, you can attach behaviours and avoid switch
statements.
You can combine these (as above) using an EnumSet. From the doc:
A specialized Set implementation for use with enum types .... This representation is extremely compact and efficient. The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based "bit flags."
回答2:
The Answer by Brian Agnew is correct. Java has a powerful, flexible, and downright handy Enum facility. (Not to be confused with the now-outmoded Enumeration interface.)
Example Code
Here is example code based on the question.
public enum Liquid {
COKE, PEPSI, JUICE, WATER
}
A method taking an EnumSet of that enum type.
public Drink makeDrink ( EnumSet<Liquid> ingredients ) {
System.out.println ( "ingredients: " + ingredients );
if ( ingredients.contains ( Liquid.JUICE ) ) {
// Treat as a Collection.
// `EnumSet` is just another `Set` implementation, though a very fast one.
}
for ( Liquid ingredient : ingredients ) {
// Access each item in the collection, each Liquid object in the EnumSet.
}
}
Code calling that method, instantiating and passing the necessary EnumSet
.
EnumSet ingredients = EnumSet.of ( Liquid.COKE , Liquid.JUICE , Liquid.WATER );
Drink drink = this.makeDrink ( ingredients );
When run.
ingredients: [COKE, JUICE, WATER]
Keep in mind these are real objects, type-safe, compiler-enforced, statically defined, and self-documenting. Do not mistake them for mere strings.
回答3:
You have also Java EnumMap, so you can get the value from the EnumMap
of all the USE_XXX
needed for your drink before pass the sums of them to your method
回答4:
There are multiple options to implement this.
- I personally like the C style way of bit manipulation just creating a enumeration or set of final statics.
- Another option in Java is to use the java.util.BitSet object.
- Probably the cleanest from a true OOP view would be to implement a utility class with boolean getter/setters. That utility class would then be passed to the object that needs to use the flags.
来源:https://stackoverflow.com/questions/11582028/proper-design-pattern-for-passing-flags-to-an-object