Java 布尔组合的开关构造

Java 布尔组合的开关构造,java,idioms,Java,Idioms,假设我有n个布尔值,其中n是一个相对较小的数字(3-5左右)。假设这些值是类的属性,每个属性都可以独立设置或取消设置。因此,有2n种可能的组合。现在我想以一种类似开关的方式来区分这些组合。目前,我通常会这样做: int mask = (bool1 ? 1 : 0) + (bool2 ? 2 : 0) + (bool3 ? 4 : 0) + ... ; switch (mask) { case 0b000: /

假设我有n个布尔值,其中n是一个相对较小的数字(3-5左右)。假设这些值是类的属性,每个属性都可以独立设置或取消设置。因此,有2n种可能的组合。现在我想以一种类似开关的方式来区分这些组合。目前,我通常会这样做:

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

这个很好用,但我觉得不太雅致。对于这样的情况,是否有一些最佳实践(Java)或Java习惯用法?

这个问题就是他们发明Java的原因。该模式允许向类中添加“特征”。例如,假设你有一个班级的咖啡。每种咖啡都可以加糖、牛奶、奶油、甜味剂或鲜奶油(假设这些都不是相互排斥的)。因此,我们不需要使用五个布尔参数(咖啡的每种特性对应一个参数)。您将具有以下层次结构:

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()));

这种设计将每个布尔参数的行为分离到一个单独的类中,从而使代码更具可读性和可扩展性。呼叫饮料将打印:“Yumm牛奶Yumm糖Yumm咖啡”

为什么不使用if语句?它比这个开关可读性强得多。这可能更适合,尽管没有投票决定是否结束。@DontRelaX如果有一些方法,为什么不把你的首选作为答案呢。想想看,当你有5个宝贝儿时,它会是什么样子。哪个位子不够优雅,不适合你?是面罩的构造还是开关的构造,还是两者兼而有之?就我个人而言,我认为它对5个非常有效,但对3个来说效果太好了。但是,
案例
块的内容是否重复?@weston。我不喜欢的是,布尔值的含义在位编码中是不可见的。此外,例如,在带有enum的交换机中,如果我忘记了一个案例,Eclipse会警告我,这里不再是这种情况了。谢谢你的回答。这是一个有趣的设计模式,但我认为它不能完全解决问题。首先,如果不存在装饰,则无法指定必须运行某些代码。其次,如果
咖啡
含牛奶的咖啡
含糖的咖啡
装饰,则执行这两种装饰的
饮料()
方法。但是,如果milk为true,我可能希望运行代码块A,如果sugar为true,则运行代码块B,如果sugar和milk都为true,则运行完全无关的代码块C。你知道装饰器模式是否可以适应以支持这一点吗?至于不存在装饰的代码,你可以编写一个不含牛奶的类Coffeewithout Milk。然后你可以写一些东西,比如不加牛奶的新咖啡(新咖啡加糖(新咖啡杯());您可以编写另一个名为CoffeeWithSugarAndMilk的类,它将做一些与CoffeeWithSugar和CoffeeWithMilk完全不同的事情。唯一的问题是用户需要知道如何使用这个类,而不是创建一个新的CoffeeWithMilk(new CoffeeWithSugar(new CupOfCoffee());