什么是替代使用多种布尔开关

问题描述:

我有一个旧的代码需要被带回生活,它采用约10-15布尔值,围绕整个班级跳舞吧,像这样:什么是替代使用多种布尔开关

if (condition) 
{ 
    bool1 = true 
} 
if (condition) 
{ 
    bool2 = true 
} 
... 

然后

if (bool1 == true && bool2 == true && bool3 == false) 
{ 
    do something 
} 
else if (bool1 == true && bool2 == false && bool3 == false) 
{ 
    do something 
} 
... 

这样可以避免编码吗?有更好的方法来实现这个吗?也许利用地图?

我想提高可读性和整体性能,因为这段代码长度超过1000行。

反馈增加更多具体的例子后:

boolean bool1 = false, bool2 = false, bool3 = false, bool4 = false, bool5 = false, 
bool6 = false, bool7 = false, bool8 = false, bool9 = false, bool10 = false; 

if (string_object.startsWith("Pattern1")) 
{ 
    bool1 = true 
} 
if (string_object.startsWith("Pattern2") 
{ 
    bool2 = true 
} 
if (string_object.startsWith("Pattern3") 
{ 
    bool3 = true 
} 
if (string_object.startsWith("Pattern4") 
{ 
    bool4 = true 
} 
if (string_object.startsWith("Pattern5") 
{ 
    bool5 = true 
} 
// and so on... 

if (system_type.equals("type1")) 
{ 
    if (bool1 == true && bool2 == true && bool3 == false) 
    { 
     system_value.set("value1") 
    } 
    else if (bool1 == true && bool2 == false && bool3 == false) 
    { 
     system_value.set("value2") 
    } 
    else if (bool1 == true && bool3 == false && bool4 == true) 
    { 
     system_value.set("value3") 
    } 
} 
else if (system_type.equals("type2")) 
{ 
    if (bool1 == true && bool2 == true && bool4 == true) 
    { 
     system_value.set("value1") 
    } 
    else if (bool1 == true && bool3 == false && bool5 == true) 
    { 
     system_value.set("value4") 
    } 
    else if (bool1 == true && bool3 == false && bool4 == true) 
    { 
     system_value.set("value5") 
    } 
} 
// and so on... 
+8

1.'bool1 == true' - >'bool1' 2.压缩取决于一组条件。 –

+4

取决于所有布尔值的目的是什么。请记住,编写代码与向未来的开发人员/维护人员沟通是一样的,因为这是为了告诉计算机要做什么。如果这些布尔人在程序所要做的事情上有明确的含义,那么只要改变他们的名字来明确这些含义。如果你的代码在重构后更有意义,那么重构。 –

+2

我会建议使用名字很好的方法,所以你从名字中看到这些条件实际上意味着什么,评估你的“条件”,并用它们代替这些'bool1''bool2' ......这些方式你可以封装这个逻辑,避免使用全局变量并使代码更具可读性 –

您可以从布尔构造位图,以及编码所需的组合为整数。

下面是一个例子:假设您需要三个布尔值,flag0flag1flag2,你需要检查标志的五种不同组合:

flag2 flag1 flag0 Action 
----- ----- ----- ---------- 
true false false ActionOne 
true true false ActionTwo 
true false true ActionThree 
false false true ActionFour 
false true true ActionFive 

然后你就可以建立标志如下:

int flags = 0; 
if (condition0) flags |= (1 << 0); 
if (condition1) flags |= (1 << 1); 
if (condition2) flags |= (1 << 2); 

现在的情况每个组合被编码成零,七,(含)之间的唯一编号,因此它可以用switch表达式来进行检查:

switch(flags) { 
    case 4: actionOne(); break; // 1 0 0 
    case 6: actionTwo(); break; // 1 1 0 
    case 5: actionThree(); break; // 1 0 1 
    case 1: actionFour(); break; // 0 0 1 
    case 3: actionFive(); break; // 0 1 1 
} 
+0

甚至更​​好,如果你使用枚举来命名它们 – Cosine

+1

@Cosine这取决于项目的一个很好的交易,但无论是枚举或详细的评论肯定是在这里。 – dasblinkenlight

+0

@Cosine,你会介意回答吗? – k4s

在这种情况下,我建议独自离开布尔值,如果他们也标记

但可以做一个整洁的事情,如果他们有密切的关系(即方向,N/S/E/W),称为bitmasks 相关堆栈溢出后:what is a bitmask and a mask

,如果你有一个街道网格他们的方向是有用的,每个路口可以有N/S/E/W的道路走出来的话,可以定义为数字的4位

让我们来定义一些常量

N=1 (0001) 
S=2 (0010) 
E=4 (0100) 
W=8 (1000) 

与N和E路的交叉口将是N |电子

N|E=1|4=5 (0101) 

一个完整的+路口(NSEW)将是N | S |电子| W

N|S|E|W=1|2|4|8=15 (1111) 

如果要添加到一个位掩码,为newmask = oldMask |方向

让我们添加s到我们的NE面膜

int newMask = oldMask | S 

oldMask是0101,S是0010,为newmask成为0111

它也有一个简单的方法来检查,如果一个方向上存在

如果我们想检查oldMask包含N个

boolean N? = (oldMask & N) != 0 

oldMask & N将隔离N位,使返回的值为N或0

大多数情况下,这种反模式是由于开发人员不希望为一种新行为创建子类。如果是这样的话,多态可能会有所帮助。

假设你有下面的类:

public class Animal { 
    private final boolean isCat; 
    private final boolean isReptile; 
    private final boolean isDog; 


    private Animal(final boolean isCat, final boolean isReptile, final boolean isDog) { 
    this.isCat = isCat; 
    this.isReptile = isReptile; 
    this.isDog = isDog; 
    } 

    public static Animal getLizard() { 
    return new Animal(false, true, true); 
    } 

    public static Animal getDog() { 
    return new Animal(false, false, false); 
    } 

    public String seeStranger() { 
    final StringBuilder result = new StringBuilder(this.toString()); 
    if (isDog) { 
     result.append(" barks and"); 
    } else if (isCat) { 
     result.append(" meows and"); 
    } 
    if (isReptile) { 
     result.append(" crawls away."); 
    } else { 
     result.append(" walks forward."); 
    } 
    return result.toString(); 
    } 
} 

你真正想要的是多种类型具有不同的行为:

public abstract class Animal { 


    public static Animal getLizard() { 
    return new Lizard(); 
    } 

    public static Animal getDog() { 
    return new Dog(); 
    } 

    public abstract String seeStranger(); 

    private static class Lizard extends Animal { 
    @Override 
    public String seeStranger() { 
     return this.toString() + " crawls away."; 
    } 
    } 

    private static class Dog extends Animal { 
    @Override 
    public String seeStranger() { 
     return this.toString() + " barks and walks forward."; 
    } 
    } 
} 

根据您的使用情况下,你可能会发现很容易与分配布尔变量,只是将条件内联放入控制流程语句中。例如,你可以改变这一点:

if (condition1) 
{ 
    bool1 = true 
} 
else if (condition2) 
{ 
    bool2 = true 
} 

... 

if (bool1 == true && bool2 == true && bool3 == false) 
{ 
    do something 
} 
else if (bool1 == true && bool2 == false && bool3 == false) 
{ 
    do something 
} 

... 

到更多的东西是这样的:

if (condition1 && condition2 && condition3) 
{ 
    do something 
} 
else if (condition1 && (not condition2) && codition3) 
{ 
    do something 
} 

... 

您可能还可以简化您的条件。例如,可能有一个condition4相当于condition1 && condition2,它不使用&&。考虑condition1 := x <= 100condition2 := x >= 100condition1 && condition2完全等同于x == 100,我肯定会建议改变

... 
bool1 = (x >= 100); 
... 
bool2 = (x <= 100); 
... 
if (bool1 == true && bool2 == true) { ... } 
... 

此相反:

... 
if (x == 100) { ... } 
... 

我毫不犹豫地走这么远来调用明确使用布尔变量的反模式,但我倾向于尽可能将布尔值作为R值。

有几件事你可以做。

  1. 如其他人提及的,这样的代码:

    如果(条件) { BOOL1 = TRUE; }

可以压缩到:

bool1 = (condition); 
  1. 另一个有用的工具是Martin Fowler的refactors之一 - Decompose Conditional
  2. 这方面的一个例子是像改变这样的:

    if (bool1 == true && bool2 == true && bool3 == false) 
    { 
        do something 
    } 
    else if (bool1 == true && bool2 == false && bool3 == false) 
    { 
        do something 
    } 
    

    为了这样的事情:

    if (firstCondition()) 
    { 
        do something 
    } 
    else if (secondCondition()) 
    { 
        do something 
    } 
    
    private boolean firstCondition() { 
        return (bool1 && bool2 && !bool3); 
    } 
    
    private boolean secondCondition() { 
        return (bool1 && !bool2 && !bool3); 
    } 
    

    分解复杂的条件语句像这样使代码更容易阅读和维护。

开始=>