莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          談NullObject模式

          Posted on 2007-07-31 17:48 dennis 閱讀(5186) 評論(7)  編輯  收藏 所屬分類: 模式與架構
              知道這個模式還是通過《重構》,這個模式的出現還是了為了解決代碼重復的壞味道。在項目中很經常見到類似下面這樣的代碼:
          if(prj.getProjectId==null)
              plan.setCost(
          0.0);
          else
              plan.setCost(prj.getCost());

             我們在很多地方有類似的檢查對象是否為null,如果為null,需要一個默認值等等這樣的場景。顯然,代碼重復是壞味道,怎么消除這個壞味道呢?答案就是使用NullObject替代之,Null Object繼承原對象。
          class NullProject extends Project{
             
          public boolean isNull(){
                
          return true;
             }
          }
          class Project{
             
          private double cost;
             
          private String projectId;
             .
             
          public boolean isNull(){
                  
          return false;
             }
          }

          那么,原來的代碼可以改寫為:
          if(prj.isNull())
              plan.setCost(
          0.0);
          else
              plan.setCost(prj.getCost());

              如果Null Object的引入僅僅是帶來這個好處,似乎沒有理由讓我們多敲這么多鍵盤。問題的關鍵是類似上面這樣的判斷也許出現在很多處,那么有價值的技巧出現了,我們在NullObject覆寫getCost,提供缺省值:
          class NullProject extends Project{
             
          public boolean isNull(){
                
          return true;
             }
             
          public double getCost(){
                
          return 0.0;      
             }
          }
              因此,檢查對象是否為null的代碼可以去掉if...else了:
          plan.setCost(prj.getCost());

              請注意,只有那些大多數客戶端代碼都要求null object做出相同響應時,這樣的行為才有意義。比如我們這里當工程id為null,很多地方要求費用就默認為0.0。 特殊的行為我們仍然使用isNull進行判斷。
              當然,另外在需要返回NullObject的地方,你應該創建一個null object以替代一般的對象,我們可以建立一個工廠方法:

          class Project{
             
          private double cost;
             
          private String projectId;
             .
             
          public boolean isNull(){
                  
          return false;
             }
             
          public Project createNullProject(){
                  
          return new NullProject();
             }
          }

             Null Object模式帶來的好處:減少了檢查對象是否為null的代碼重復,提高了代碼的可讀性,通常這些Null Object也可以為單元測試帶來簡便。


          評論

          # re: 談NullObject模式[未登錄]  回復  更多評論   

          2007-07-31 23:47 by xmlspy
          很早以前用過這個模式,不過感覺實在沒有必要
          很麻煩

          # re: 談NullObject模式  回復  更多評論   

          2007-08-01 07:48 by dennis
          @xmlspy
          如果只是少數地方有這樣的條件判斷,我也認為實在沒有必要,不過在我們項目的場景中,賦予默認值以及check null經常出現,因此使用此模式后確實大幅度減少了重復代碼,取舍之間就看大家自己判斷

          # re: 談NullObject模式  回復  更多評論   

          2007-08-01 09:25 by dreamstone
          對于長業務流程,多個條件分支的情況下還是挺有用的。
          記得曾經做過一個報文解析系統,當時我為了遍歷樹不為空做過一個類似的結構。

          # re: 談NullObject模式  回復  更多評論   

          2007-08-01 11:31 by 金大為
          我想,我們常常用的 Collections.EMPTY_LIST之類的空列表,空map。
          和這里說的NullObject算是同一類技巧吧。

          # re: 談NullObject模式  回復  更多評論   

          2007-08-01 13:43 by dennis
          @金大為
          有點類似的味道,java的collection框架真是模式大集合

          # re: 談NullObject模式  回復  更多評論   

          2007-08-03 09:35 by 一名
          這是故意讓null作為一種值來傳遞時候用的吧?如果我在數據庫查詢時候,出現異常,or映射的框架返回的null對象,那怎么辦?不是還是要判斷是否為null的情況嗎?

          # re: 談NullObject模式  回復  更多評論   

          2007-08-03 09:43 by dennis
          @一名
          這時候你應當返回一個NullObject,而不是一般的Object。這個模式有一定的適用場景,請看文中所述
          主站蜘蛛池模板: 钦州市| 阜平县| 五寨县| 香格里拉县| 湟源县| 漯河市| 葫芦岛市| 炉霍县| 合水县| 温州市| 永定县| 蕲春县| 高州市| 平江县| 蓬莱市| 瑞昌市| 巴林左旗| 明光市| 凉山| 乃东县| 西峡县| 安新县| 衡山县| 九台市| 化州市| 海安县| 福海县| 丽水市| 西充县| 棋牌| 连江县| 惠州市| 安岳县| 天峻县| 乌兰察布市| 广元市| 元谋县| 博白县| 茂名市| 星子县| 富阳市|