Switch construct for combinations of booleans

338 Views Asked by At

Suppose I have n boolean values, where n is a relatively small number (3-5 or so). Let's say that the values are properties of a class, each of which can be set or unset independently. So, there are 2n possible combinations. Now I want to distinguish between these combinations in a switch-like fashion. Currently, I usually do something like this:

int mask = (bool1 ? 1 : 0) +
           (bool2 ? 2 : 0) +
           (bool3 ? 4 : 0) +
           ... ;
switch (mask) {
    case 0b000:
       // all variables false
    case 0b001:
       // only bool1 true
    case 0b011:
       // only bool1 and bool2 true
    ...
}

This works all right, but I do not find it very elegant. Is there some best practice (in Java) or Java idiom for cases like this?

1

There are 1 best solutions below

2
On

This problem is the reason they invented the Decorator Design Pattern. The pattern allows for adding "traits" to your class. For instance let's say you have a class Coffee. Each instance of coffee can be with sugar, milk, creamer, sweetener or whipped cream (let's say none of these are mutually exclusive). So instead of having five boolean parameters (one for each trait of coffee). You will have the following hierarchy:

public interface Coffee {
  public void drink();
}

public class CupOfCofee implements Coffee {
  public void drink() {
    print("Yumm coffee");
  }
}

abstract class CoffeeDecorator implements Coffee {
  protected Coffee decoratedCoffee;

  public CoffeeDecorator(Coffee decoratedCoffee) {
    this.decoratedCoffee = decoratedCoffee;
  }

  public void drink() {
    decoratedCoffee.drink();
  }
}

// We will provide coffee with sugar as an example.
public class CoffeeWithSugarDecorator extends CoffeeDecorator {
  public CoffeeWithSugarDecorator(Coffee decoratedCoffee) {
    super(decoratedCoffee);
  }

  @Override
  public void drink() {
    print("Yumm sugar");
    super.drink();
  }
}

// Here is how you will initialize a coffee instance with sugar and milk.
Coffee coffee = new CoffeeWithMilk(new CoffeeWithSugar(new CupOfCoffee()));

This design makes your code much more readable and extensible by separating the behaviors of each boolean parameter to a separate class. Calling drink will print: "Yumm milk Yumm sugar Yumm coffee"