2013-05-20 53 views
2

首先,我想說我沒有太多的重構經驗,不知道這是不是主題。避免布爾型標誌作爲屬性

我正在使用給定的代碼,其中使用了很多布爾屬性,我想避免這種情況,因爲可讀性,我不知道如何以正確的方式處理它。

class MyClass(){ 
    boolean a; 
    ... 
    void function(){ 
     ... 
     a = true; 
     ... 
    } 

    void anotherFunction(){ 
     ... 
     if(a == true){ 
      //do something 
     } else { 
      //do something else 
     } 
     ... 
    } 
    ... 
} 

boolean a在多個用於function就像這樣,其中anotherFunction s的運行關於到a的代碼。由於在anotherFunction中使用了多個屬性和局部變量,所以很難理解代碼和依賴關係,並且難以重構它。重構這個的努力可能會非常高。

我一直試圖避免使用這樣的布爾值,因爲在我看來,它不是很好的做法。如果我錯了,請毫不猶豫地糾正我。

現在我想知道我是否應該重構代碼並花費精力?在這種情況下可以使用某種模式嗎?

回答

5

你可以使用狀態模式。根據布爾變量在單獨的摘要State類中封裝狀態和行爲。當布爾值設置爲false時,將狀態更改爲FalseState(它擴展了State)的實例,並委派給此實例FalseState。如果布爾值設置爲true,則將狀態更改爲TrueState的實例,並委託給此實例TrueState

例如,下面的類

public class Apple { 

    private boolean fresh = false; 

    public String getColor() { 
     if (fresh) { 
      return "green"; 
     } 
     else { 
      return "brown"; 
     } 
    } 

    public void setFresh(boolean fresh) { 
     this.fresh = fresh; 
    } 
} 

可重構爲

public class Apple { 

    private AppleState state = new OldAppleState(); 

    public String getColor() { 
     return state.getColor(); 
    } 

    public void setFresh(boolean fresh) { 
     this.state = state.nextState(fresh); 
    } 

    public String getColor() { 
     return this.state.getColor(); 
    } 

    private static abstract class State { 
     public abstract State nextState(boolean fresh); 
     public abstract String getColor(); 
    } 

    private static class OldAppleState extends State{ 
     public State nextState(boolean fresh) { 
      return fresh ? new FreshAppleState() : this; 
     } 
     public String getColor() { 
      return "brown"; 
     } 
    } 


    private static class FreshAppleState extends State{ 
     public State nextState(boolean fresh) { 
      return fresh ? this : new OldAppleState(); 
     } 
     public String getColor() { 
      return "green"; 
     } 
    } 
} 

我用內部類,當然你可以使用頂級類。

+0

這對於定義不同的狀態非常好。感謝那。 –

2

你給出的代碼示例顯然有些截斷,但在我看來,這個類的行爲類似於state machine

如果在類中有許多布爾屬性,並且它們都決定了該函數中方法的行爲,那麼您很快就會遇到可能性的爆炸式增長,並且代碼會變得難以遵循 - 最終會導致代碼如:

if (true == a && false == b){ 
    ... 
} 
elseif (false == a && false == b){ 
    .... 
} 

等等。

您可以應用的第一個重構是創建狀態查找方法;這個轉換上面的代碼:

if (aNotB == getState(a, b)){ 
    .... 
} 
elseif (notANotB == getState(a, b)){ 
    ... 
} 

這使得代碼更容易一些,並迫使你想在應用程序,而不是單個布爾值的狀態而言。

如果需要的話,您可以轉到完整的狀態機 - 大多數編程語言都有跨網站的參考實現。

+0

是的,可能的組合來定義一個狀態真的很煩人! –

1

關於狀態轉換邏輯的思考是至關重要的。我會更進一步,用枚舉清楚地定義你的狀態。

public enum AppState { 
    ST1(false, false), 
    ST2(false, true), 
    ST3(true, false), 
    ST4(true, true); 
    private Boolean x, y; 
} 

使用枚舉的一個特別有用的優點是能夠定義模板方法 - Template methods using enums。將讓你簡化你的功能來匹配你的狀態,並使其更加面向對象。

+0

將枚舉定義爲枚舉對我來說聽起來不錯。 –

1

如果多次使用布爾值a,我更喜歡monad-like內部類函數。

public class BoolAHandler{ 
    public bool A = false; 
    public BoolAHandler IfTrue(Action act){ 
     if(A){ 
      act(); 
     } 
     return this; 
    } 
    public BoolAHandler IfFalse(Action act){ 
     if(!A){ 
      act(); 
     } 
     return this; 
    } 
} 

用法:

boolAHandler.IfTrue(() => { doFunctionA(); }) 
      .IfFalse(() => { doFunctionB(); }); 

當然,如果布爾一個具有意義,你可以把它調整到意義了。說如果它處理髮布狀態,則可以將IfTrue更改爲IfAlreadyPublishedIfFalseIfNotPublished

+0

以前從未聽說過monad。感謝那。 –