Proper design pattern for passing flags to an object

半城伤御伤魂 提交于 2019-12-11 13:35:34

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!