2017-10-12 78 views
0

我有一箇舊的代碼需要被帶回生活,它採用約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' ......這些方式你可以封裝這個邏輯,避免使用全局變量並使代碼更具可讀性 –

回答

1

您可以從布爾構造位圖,以及編碼所需的組合爲整數。

下面是一個例子:假設您需要三個布爾值,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

0

在這種情況下,我建議獨自離開布爾值,如果他們也標記

但可以做一個整潔的事情,如果他們有密切的關係(即方向,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

1

大多數情況下,這種反模式是由於開發人員不希望爲一種新行爲創建子類。如果是這樣的話,多態可能會有所幫助。

假設你有下面的類:

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."; 
    } 
    } 
} 
1

根據您的使用情況下,你可能會發現很容易與分配布爾變量,只是將條件內聯放入控制流程語句中。例如,你可以改變這一點:

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值。

3

有幾件事你可以做。

  1. 如其他人提及的,這樣的代碼:

    如果(條件) { 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); 
    } 
    

    分解複雜的條件語句像這樣使代碼更容易閱讀和維護。