什么是替代使用多种布尔开关
我有一个旧的代码需要被带回生活,它采用约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...
您可以从布尔构造位图,以及编码所需的组合为整数。
下面是一个例子:假设您需要三个布尔值,flag0
,flag1
和flag2
,你需要检查标志的五种不同组合:
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
}
甚至更好,如果你使用枚举来命名它们 – Cosine
@Cosine这取决于项目的一个很好的交易,但无论是枚举或详细的评论肯定是在这里。 – dasblinkenlight
@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 <= 100
和condition2 := x >= 100
。 condition1 && condition2
完全等同于x == 100
,我肯定会建议改变
...
bool1 = (x >= 100);
...
bool2 = (x <= 100);
...
if (bool1 == true && bool2 == true) { ... }
...
此相反:
...
if (x == 100) { ... }
...
我毫不犹豫地走这么远来调用明确使用布尔变量的反模式,但我倾向于尽可能将布尔值作为R值。
有几件事你可以做。
-
如其他人提及的,这样的代码:
如果(条件) { BOOL1 = TRUE; }
可以压缩到:
bool1 = (condition);
- 另一个有用的工具是Martin Fowler的refactors之一 - Decompose Conditional。
这方面的一个例子是像改变这样的:
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);
}
分解复杂的条件语句像这样使代码更容易阅读和维护。
1.'bool1 == true' - >'bool1' 2.压缩取决于一组条件。 –
取决于所有布尔值的目的是什么。请记住,编写代码与向未来的开发人员/维护人员沟通是一样的,因为这是为了告诉计算机要做什么。如果这些布尔人在程序所要做的事情上有明确的含义,那么只要改变他们的名字来明确这些含义。如果你的代码在重构后更有意义,那么重构。 –
我会建议使用名字很好的方法,所以你从名字中看到这些条件实际上意味着什么,评估你的“条件”,并用它们代替这些'bool1''bool2' ......这些方式你可以封装这个逻辑,避免使用全局变量并使代码更具可读性 –