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