设计模式(六)------设计模式六大原则(5):迪米特法则
轉(zhuǎn)載自:http://www.jianshu.com/p/14589fb6978e (作者簡(jiǎn)書:涅槃1992)
揭秘迪米特法則
迪米特法則(Law of demeter,縮寫是LOD)要求:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少了解, 通縮的講就是一個(gè)類對(duì)自己依賴的類知道的越少越好,也就是對(duì)于被依賴的類,向外公開的方法應(yīng)該盡可能的少。
迪米特法則還有一種解釋:Only talk to your immediate friends,即只與直接朋友通信.首先來解釋編程中的朋友:兩個(gè)對(duì)象之間的耦合關(guān)系稱之為朋友,通常有依賴,關(guān)聯(lián),聚合和組成等.而直接朋友則通常表現(xiàn)為關(guān)聯(lián),聚合和組成關(guān)系,即兩個(gè)對(duì)象之間聯(lián)系更為緊密,通常以成員變量,方法的參數(shù)和返回值的形式出現(xiàn).
那么為什么說是要與直接朋友通信呢?觀察直接朋友出現(xiàn)的地方,我們發(fā)現(xiàn)在直接朋友出現(xiàn)的地方,大部分情況下可以接口或者父類來代替,可以增加靈活性. (需要注意,在考慮這個(gè)問題的時(shí)候,我們只考慮新增的類,而忽視java為我們提供的基礎(chǔ)類.)
實(shí)例演示
不難發(fā)現(xiàn),迪米特法則強(qiáng)調(diào)了一下兩點(diǎn):
- 第一要義:從被依賴者的角度來說:只暴露應(yīng)該暴露的方法或者屬性,即在編寫相關(guān)的類的時(shí)候確定方法/屬性的權(quán)限
- 第二要義:從依賴者的角度來說,只依賴應(yīng)該依賴的對(duì)象
先來解釋第一點(diǎn),我們使用計(jì)算機(jī)來說明,以關(guān)閉計(jì)算機(jī)為例:
當(dāng)我們按下計(jì)算機(jī)的關(guān)機(jī)按鈕的時(shí)候,計(jì)算機(jī)會(huì)執(zhí)行一些列的動(dòng)作會(huì)被執(zhí)行:比如保存當(dāng)前未完成的任務(wù),然后是關(guān)閉相關(guān)的服務(wù),接著是關(guān)閉顯示器,最后是關(guān)閉電源,這一系列的操作以此完成后,計(jì)算機(jī)才會(huì)正式被關(guān)閉。
現(xiàn)在,我們來用簡(jiǎn)單的代碼表示這個(gè)過程,在不考慮迪米特法則情況下,我們可能寫出以下代碼
//計(jì)算機(jī)類 public class Computer{public void saveCurrentTask(){//do something}public void closeService(){//do something}public void closeScreen(){//do something}public void closePower(){//do something}public void close(){saveCurrentTask();closeService();closeScreen();closePower();} }//人 public class Person{private Computer c;...public void clickCloseButton(){//現(xiàn)在你要開始關(guān)閉計(jì)算機(jī)了,正常來說你只需要調(diào)用close()方法即可,//但是你發(fā)現(xiàn)Computer所有的方法都是公開的,該怎么關(guān)閉呢?于是你寫下了以下關(guān)閉的流程: c.saveCurrentTask();c.closePower();c.close();//亦或是以下的操作 c.closePower();//還可能是以下的操作c.close();c.closePower();}}發(fā)現(xiàn)上面的代碼中的問題了沒?
我們觀察clickCloseButton()方法,我們發(fā)現(xiàn)這個(gè)方法無法編寫:c是一個(gè)完全暴露的對(duì)象,其方法是完全公開的,那么對(duì)于Person來說,當(dāng)他想要執(zhí)行關(guān)閉的時(shí)候,卻發(fā)現(xiàn)不知道該怎么操作:該調(diào)用什么方法?靠運(yùn)氣猜么?如果Person的對(duì)象是個(gè)不按常理出牌的,那這個(gè)Computer的對(duì)象豈不是要被搞壞么?
迪米特法則第一要義
現(xiàn)在我們來看看迪米特法則的第一點(diǎn):從被依賴者的角度,只應(yīng)該暴露應(yīng)該暴露的方法。那么這里的c對(duì)象應(yīng)該哪些方法應(yīng)該是被暴露的呢?很顯然,對(duì)于Person來說,只需要關(guān)注計(jì)算機(jī)的關(guān)閉操作,而不關(guān)心計(jì)算機(jī)會(huì)如何處理這個(gè)關(guān)閉操作,因此只需要暴露close()方法即可。
那么上述的代碼應(yīng)該被修改為:
看一下它的類圖:
接下來,我們繼續(xù)來看迪米特法則的第二層含義:從依賴者的角度來說,只依賴應(yīng)該依賴的對(duì)象。 這句話令人有點(diǎn)困惑,什么叫做應(yīng)該依賴的對(duì)象呢?我們還是用上面“關(guān)閉計(jì)算機(jī)”的例子來說明: 準(zhǔn)確的說,計(jì)算機(jī)包括操作系統(tǒng)和相關(guān)硬件,我們可以將其劃分為System對(duì)象和Container對(duì)象。當(dāng)我們關(guān)閉計(jì)算機(jī)的時(shí)候,本質(zhì)上是向操作系統(tǒng)發(fā)出了關(guān)機(jī)指令,而實(shí)則我們只是按了一下關(guān)機(jī)按鈕,也就是我們并沒有依賴System的對(duì)象,而是依賴了Container。這里Container就是我們上面所說的直接朋友---只和直接朋友通信.
我們就這點(diǎn),繼續(xù)深入討論一下: only talk to your immedate friends 這句話只說明了要和直接朋友通信,但是我覺得這還不完整,我更愿意將其補(bǔ)充為: make sure your friends,only talk to your immedate friends,don't speak to strangers. 大意是:確定你真正的朋友,并只和他們通信,并且不要和陌生人講話.這樣做有個(gè)很大的好處就是,能夠簡(jiǎn)化對(duì)象與對(duì)象之間的通信,進(jìn)而減輕依賴,提供更高的靈活性,當(dāng)然也可以提供一定的安全性.
現(xiàn)在來想想現(xiàn)實(shí)世界中的這么一種情況:你是一個(gè)令人矚目的公眾人物,周圍的每個(gè)人都知道你的名字,當(dāng)你獨(dú)自走在大街上的時(shí)候會(huì)是怎么樣的一種場(chǎng)景?每個(gè)人都想要和你聊天!,和你交換信息!!接著,你發(fā)現(xiàn)自己已經(jīng)寸步難行了.如果這時(shí)候你有一個(gè)經(jīng)紀(jì)人,來幫你應(yīng)對(duì)周圍的人,而你就只和這個(gè)經(jīng)紀(jì)人通信,這樣就大大減輕了你的壓力,不是么?此時(shí),這個(gè)經(jīng)濟(jì)人就相當(dāng)于你的直接朋友.
迪米特法則第二要義
現(xiàn)在,我們?cè)倩仡?#34;關(guān)機(jī)計(jì)算機(jī)"這個(gè)操作,前面的代碼只是遵從了"暴漏應(yīng)該暴漏的方法"這一點(diǎn),現(xiàn)在我們結(jié)合第二點(diǎn)來進(jìn)行改進(jìn):System和Container相比,System并非Person的直接朋友,而Container才是(Person直接打交道的是Container).因此我們需要將原有的Computer拆分成System和Cotainer,然后使Person只與Container通信,因此代碼修改為:
//操作系統(tǒng) public class System{private void saveCurrentTask(){//do something}private void closeService(){//do something}private void closeScreen(){//do something}private void closePower(){//do something}public void close(){saveCurrentTask();closeService();closeScreen();closePower();} }//硬件設(shè)備容器 public class Container{private System mSystem;public void sendCloseCommand(){mSystem.close();} }//人 ublic class Person{private Container c;....public void clickCloseButton(){c.sendCloseCommand();}}來看一下它的類圖:
對(duì)比這兩種方案,明顯這種方案二的解耦程度更高,靈活大大增強(qiáng).不難發(fā)現(xiàn),這應(yīng)用了我們前面提到的依賴倒置,即面向接口編程.
除此之外,我們發(fā)現(xiàn)隨著不斷的改進(jìn),類的數(shù)量也在不斷的增加,從2個(gè)增加到5個(gè),這意味著為了解耦和提高靈活性通常要編寫的類的數(shù)量會(huì)翻倍.因此,你需要在這做一個(gè)權(quán)衡,切莫刻意為了追求設(shè)計(jì),而導(dǎo)致整個(gè)系統(tǒng)非常的冗余,最終可能得不償失.
總結(jié)
有人會(huì)覺得Container像是一個(gè)中介(代理).沒錯(cuò),我們確實(shí)可以稱其為中介,但這并不能否認(rèn)他是我們的直接朋友:在很多情況下,中介可以說是我們的一種代表,因此將其定義為直接朋友是沒有任何問題的.比如,當(dāng)你想要租房的時(shí)候,你可以找房屋中介,對(duì)方會(huì)按照你的標(biāo)準(zhǔn)為你尋找合適的住房.但是問題來了:那么做一件事情需要多少中介呢?總不能是我委托一個(gè)中介A幫我找房子,但中介A又委托了中介B,中介B又委托了中介C....等等,如果真的是這樣,那還不如我自己去找房子效率更高.在實(shí)際開發(fā)中,委托的層次要控制在6層以下,多余6層以上的會(huì)使得系統(tǒng)過分的冗余和并切會(huì)委托層次過多而導(dǎo)致開發(fā)人員無法正確的理解流程,產(chǎn)生風(fēng)險(xiǎn)的可能會(huì)大大提高.
到目前,我們已經(jīng)徹底的了解了迪米特法則.
轉(zhuǎn)載于:https://www.cnblogs.com/chz-blogs/p/9380982.html
總結(jié)
以上是生活随笔為你收集整理的设计模式(六)------设计模式六大原则(5):迪米特法则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网上售票系统第五天
- 下一篇: SQL优化器-RBO与CBO分别是什么