Proper design pattern for passing flags to an obje

2019-07-27 07:48发布

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.

4条回答
家丑人穷心不美
2楼-- · 2019-07-27 08:28

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

查看更多
何必那么认真
3楼-- · 2019-07-27 08:36

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."

查看更多
时光不老,我们不散
4楼-- · 2019-07-27 08:48

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.
查看更多
你好瞎i
5楼-- · 2019-07-27 08:50

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.

查看更多
登录 后发表回答