設計模式6大原則(5):迪米特法則

迪米特法則

迪米特法則:Law of Demeter(LoD)

       設計模式6大原則中,怎麼出現一個法則呢?原則強調說話行事的準則,規則;法則強調規律,法度規範。不過這裏我們不討論文字,1987年秋天由美國Northeastern University的Ian Holland提出,被UML的創始者之一Booch等普及。後來,因爲在經典著作《 The Pragmatic Programmer》而廣爲人知。迪米特法則還有一個別名:

最少知識原則:Least Knowledge Principle(LKP)

       這下就清晰多了,意思就是一個對象應該對其他對象儘可能的少了解,不和陌生人說話。簡單的說,就是我知道你提供的這幾個public方法,我就調用這幾個,其他的我不管,你內部怎麼實現的我也不管。迪米特法則還包含了以下4層含義:

       1.只與朋友通信:Only talk to your immedate friends。

       什麼意思呢?舉例說明,比如想知道某人付錢時是否有足夠的錢

  

  public void buy(Good good) {
       if (person.getWallet().getMoney()< good.getPrice()) {
           throw new Exception("錢不夠");
       }
…………
    } 

       人先獲得了錢包,然後獲取錢,然後比價格,看似很正常,挺好的代碼。確實很好,運行起來沒有問題,但是卻違反了迪米特法則,因爲此處buy這個方法所在的類依賴了Wallet錢包這個類,其實他完全可以不需要知道錢包的。

       換正常生活中的例子,你去買東西,賣家要看你錢夠不夠,會去掏你錢包,然後看看錢是否夠嗎?當然不會,雖然結果一樣,都可以完成,但是不符合正常人思維。況且,人不一定都有錢包呀,萬一有個人沒有錢包呢,但是卻有錢,或者錢包類有一天改了,沒有getMoney()方法了,改名叫money()怎麼辦,難道買東西這個方法也要改嗎?想想正常生活中我們是怎麼去決定是否有錢的。

    public void buy(Good good) {
       if (!person.isEnough(good.getPrice())){
           throw new Exception("錢不夠");
       }
       …………
}


       這樣是不是就符合實際多了,看着也好理解了,直接問人錢是否夠,賣家不管你人內部怎麼處理的,他只與人這個類有接觸,所以他倆是朋友,他不關心錢包不錢包。

       只與朋友通信就是這個意思,代碼中不要出現getA().getB().getC().getD()這種情況(如果返回結果是自身,那麼是可以的),當然,此處說的朋友類之間,是指自己創建的類,JDK API提供的類除外。

       2.朋友間也是有距離的

       前面說了只與朋友通信,那麼朋友間就可以無限制的通信嗎,當然不是,朋友類之間也是有距離的,就像兩個刺蝟取暖,不能太遠,也不能太近。也就是說即使是朋友間,也要知道的最少,我不需要知道你太多的東西,知道越少,耦合越小嘛。

       說白了,就是能不用public就不用public,多用private和protected,類一定要羞澀,public越多,維護成本越大,風險越大。

       3.是自己的就是自己的

       上面那個例子,就不如把buy放到Person類中,這樣調用者就不用管是否錢夠,只需person.buy(good)一下即可。這個buy()方法,放到person中也行,放到外邊也行,那怎麼決定呢?有一個原則:如果一個方法放在本類中,即不增加類間關係,也不對本類產生負面影響,那就可以放到本類中。

       ok,最後說一下,迪米特法則核心觀念就是解耦、弱耦合,只有弱耦合後,類的複用率纔可以提高。知道的少,不知道的不管,如果一個類跳轉兩次以上才能訪問另一個類,那麼就需要考慮重構了,因爲跳轉次數越多,系統越複雜,維護起來越困難,不過這個情況要具體分析。解耦和也是要有限度的,別爲了套用原則而做項目,一味地追求解耦結果就是產生了大量的中轉或跳轉類,導致系統複雜性提高,維護困難,實際生產中應該反覆權衡。

       總結一下

              ①在類的劃分上,應該創建有弱耦合的類;

              ②在類的結構設計上,每一個類都應當儘量降低成員的訪問權限;

              ③在類的設計上,只要有可能,一個類應當設計成不變類;

              ④在對其他類的引用上,一個對象對其它對象的引用應當降到最低;

              ⑤儘量降低類的訪問權限;

              ⑥謹慎使用序列化功能;

              ⑦不要暴露類成員,而應該提供相應的訪問器(屬性)。


 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章