国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

設計模式原則之迪米特法則

2019-11-14 23:38:43
字體:
來源:轉載
供稿:網友
設計模式原則之迪米特法則

迪米特法則的簡寫為 LoD,看清楚中間的那個 o 是小寫。迪米特法則也叫做做最少知識原則(Least Knowledge PRinciple,簡稱 LKP)說的都是一會事,一個對象應該對其他對象有最少的了解,通俗的講一 個類對自己需要耦合或者調用的類應該知道的最少,你類內部是怎么復雜、怎么的糾纏不清都和我沒關系, 那是你的類內部的事情,我就知道你提供的這么多 public 方法,我就調用這個;迪米特法則包含以下四層 意思:

只和朋友交流。迪米特還有一個英文解釋叫做“Only talk to your immedate friends”,只和直接 的朋友通信,什么叫做直接的朋友呢?每個對象都必然會和其他對象有耦合關系,兩個對象之間的耦合就 成為朋友關系,這種關系有很多比如組合、聚合、依賴等等。我們來說個例子說明怎么做到只和朋友交流。 說是有這么一個故事,老師想讓體育委員確認一下全班女生來齊沒有,就對他說:“你去把全班女生清 一下。”體育委員沒聽清楚,或者是當時腦子正在回憶什么東西,就問道:“親哪個?”老師¥#……¥%。 我們來看這個笑話怎么用程序來實現,先看類圖:

Teacher.java 的源程序如下:

package com.cbf4life.common;import java.util.ArrayList;import java.util.List;/*** I'm glad to share my knowledge with you all.* 老師類*/public class Teacher {//老師對學生發布命令, 清一下女生public void commond(GroupLeader groupLeader){ List<Girl> listGirls = new ArrayList() ; //初始化女生 for(int i=0;i<20;i++){ listGirls.add(new Girl()); } //告訴體育委員開始執行清查任務 groupLeader.countGirls(listGirls); }}

老師就有一個方法,發布命令給體育委員,去清查一下女生的數量。 下面是體育委員 GroupLeader.java 的源程序:

package com.cbf4life.common;import java.util.List;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 體育委員,這個太難翻譯了都是中國的特色詞匯*/public class GroupLeader {//有清查女生的工作public void countGirls(List<Girl> listGirls){ System. out.println(" 女生數量是: "+listGirls.size()); }}

下面是 Girl.java,就聲明一個類,沒有任何的代碼:

package com.cbf4life.common;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 女生*/public class Girl {}

我們來看這個業務調用類 Client:

package com.cbf4life.common;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 我們使用Client來描繪一下這個場景*/public class Client {public static void main(String[] args) { Teacher teacher= new Teacher(); //老師發布命令 teacher.commond(new GroupLeader()); }}

運行的結果如下:

女生數量是: 20

我們回過頭來看這個程序有什么問題,首先來看 Teacher 有幾個朋友,就一個 GroupLeader 類,這個 就是朋友類,朋友類是怎么定義的呢? 出現在成員變量、方法的輸入輸出參數中的類被稱為成員朋友類, 迪米特法則說是一個類只和朋友類交流, 但是 commond 方法中我們與 Girl 類有了交流,聲明了一個 List動態數組,也就是與一個陌生的類 Girl 有了交流,這個不好,那我們再來修改一下,類圖還是不變,先修改一下 GroupLeader 類,看源碼

package com.cbf4life.common2;import java.util.ArrayList;import java.util.List;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 體育委員,這個太難翻譯了都是中國的特色詞匯*/public class GroupLeader {//有清查女生的工作public void countGirls(){ List<Girl> listGirls = new ArrayList<Girl>(); //初始化女生 for(int i=0;i<20;i++){ listGirls.add(new Girl()); } System. out.println(" 女生數量是: "+listGirls.size()); }}

下面是 Teacher.java 程序:

package com.cbf4life.common2;/*** * I'm glad to share my knowledge with you all.* 老師類*/public class Teacher {//老師對學生發布命令, 清一下女生public void commond(GroupLeader groupLeader){ //告訴體育委員開始執行清查任務 groupLeader.countGirls(); }}

程序做了一個簡單的修改,就是把 Teacher 中的對 List初始化(這個是有業務意義的,產生出 全班的所有人員)移動到了 GroupLeader 的 countGrils 方法中,避開了 Teacher 類對陌生類 Girl 的訪問, 減少系統間的耦合。記住了,一個類只和朋友交流,不與陌生類交流, 不要出現 getA().getB().getC().getD() 這種情況(在一種極端的情況下是允許出現這種訪問:每一個點號后面的返回類型都相同),那當然還要和 JDK API 提供的類交流,否則你想脫離編譯器存在呀!

朋友間也是有距離的。人和人之間是有距離的,太遠就不是朋友了,太近就渾身不自在,這和類間關 系也是一樣,即使朋友類也不能無話不說,無所不知。大家在項目中應該都碰到過這樣的需求:調用一個 類,然后必須是先執行第一個方法,然后是第二個方法,根據返回結果再來看是否可以調用第三個方法, 或者第四個方法等等,我們用類圖表示一下:

很簡單的類圖,實現軟件安裝過程的第一步做什么、第二步做什么、第三步做什么這樣一個過程,我 們來看三個類的源代碼,先看 Wizard 的源代碼:

package com.cbf4life.common3;import java.util.Random;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 按照步驟執行的業務邏輯類*/public class Wizard {private Random rand = new Random(System. currentTimeMillis());public int first(){ System. out.println(" 執行第一個方法..."); return rand.nextInt(100); }//第二步public int second(){ System. out.println(" 執行第二個方法..."); return rand.nextInt(100); }//第三個方法public int third(){ System. out.println(" 執行第三個方法..."); return rand.nextInt(100); }}

分別定義了三個步驟方法,每個步驟中都有相關的業務邏輯完成指定的任務,我們使用一個隨機函數 來代替業務執行的返回值。再來看軟件安裝過程 InstallSoftware 源碼:

package com.cbf4life.common3;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 業務組裝類,負責調用各個步驟*/public class InstallSoftware {public void installWizard(Wizard wizard){ int first = wizard.first(); //根據first返回的結果,看是否需要執行second if(first>50){ int second = wizard.second(); if(second>50){ int third = wizard.third(); if(third >50){ wizard.first(); } }}}}

其中 installWizard 就是一個向導式的安裝步驟,我們看場景是怎么調用的:

package com.cbf4life.common3;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 業務場景*/public class Client {public static void main(String[] args) { InstallSoftware invoker = new InstallSoftware(); invoker.installWizard(new Wizard()); }}

這個程序很簡單,運行結果和隨機數有關,我就不粘貼上來了。我們想想這個程序有什么問題嗎? Wizard 類把太多的方法暴露給 InstallSoftware 類了,這樣耦合關系就非常緊了,我想修改一個方法的返 回值,本來是 int 的,現在修改為 boolean,你看就需要修改其他的類,這樣的耦合是極度不合適的, 迪米 特法則就要求類“小氣”一點,盡量不要對外公布太多的 public 方法和非靜態的 public 變量, 盡量內斂, 多使用 private,package-private、protected 等訪問權限。我們來修改一下類圖:

我們再來看一下程序的變更,先看 Wizard 程序:

package com.cbf4life.common4;import java.util.Random;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 按照步驟執行的業務邏輯類*/public class Wizard {private Random rand = new Random(System. currentTimeMillis());//第一步private int first(){ System. out.println(" 執行第一個方法..."); return rand.nextInt(100); }//第二步private int second(){ System. out.println(" 執行第二個方法..."); return rand.nextInt(100); }//第三個方法private int third(){ System. out.println(" 執行第三個方法..."); return rand.nextInt(100); }//軟件安裝過程public void installWizard(){ int first = this.first(); //根據first返回的結果,看是否需要執行second if(first>50){ int second = this.second(); if(second>50){ int third = this.third(); if(third >50){ this.first(); } } } }}

三個步驟的訪問權限修改為 private,同時把 installeWizad 移動的 Wizard 方法中,這樣 Wizard 類就 對外只公布了一個 public 方法,類的高內聚特定顯示出來了。我們再來看 InstallSoftware 源碼:

package com.cbf4life.common4;/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 業務組裝類,負責調用各個步驟*/public class InstallSoftware {public void installWizard(Wizard wizard){ //不廢話,直接調用 wizard.installWizard(); }}

Client 類沒有任何改變,就不在拷貝了,這樣我們的程序就做到了弱耦合,一個類公布越多的 public 屬性或方法,修改的涉及面也就越大,也就是變更引起的風險就越大。因此為了保持朋友類間的距離,你 需要做的是:減少 public 方法,多使用 private、package-private(這個就是包類型,在類、方法、變量 前不加訪問權限,則默認為包類型)protected 等訪問權限,減少非 static 的 public 屬性,如果成員變量 或方法能加上 final 關鍵字就加上,不要讓外部去改變它。

是自己的就是自己的。在項目中有一些方法,放在本類中也可以,放在其他類中也沒有錯誤,那怎么 去衡量呢?你可以堅持這樣一個原則: 如果一個方法放在本類中,即不增加類間關系,也對本類不產生負 面影響,就放置在本類中。

謹慎使用 Serializable。實話說,這個問題會很少出現的,即使出現也會馬上發現問題。是怎么回事呢? 舉個例子來說,如果你使用 R M I 的方式傳遞一個對象 VO( Va lu e Object),這個對象就必須使用 Serializable 接口,也就是把你的這個對象進行序列化,然后進行網絡傳輸。突然有一天,客戶端的 VO 對象修改了一個 屬性的訪問權限,從 private 變更為 public 了,如果服務器上沒有做出響應的變更的話,就會報序列化失敗。 這個應該屬于項目管理范疇,一個類或接口客戶端變更了,而服務端沒有變更,那像話嗎?!

迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以后,類的復用率才可以提高,其要求 的結果就是產生了大量的中轉或跳轉類,類只能和朋友交流,朋友少了你業務跑不起來,朋友多了,你項 目管理就復雜,大家在使用的時候做相互權衡吧。

不知道大家有沒有聽過這樣一個理論:“任何 2 個素不相識的人中間最多只隔著 6 個人,即只用 6 個人 就可以將他們聯系在一起”,這個理論的學名叫做“六度分離”,應用到我們項目中就是說我和我要調用的 類之間最多有 6 次傳遞,呵呵,這只能讓大家當個樂子來看,在實際項目中你跳兩次才訪問到一個類估計 你就會想辦法了,這也是合理的,迪米特法則要求我們類間解耦,但是解耦是有限度的,除非是計算機的 最小符號二進制的 0 和 1,那才是完全解耦,我們在實際的項目中時,需要適度的考慮這個法則,別為了套 用法則而做項目,法則只是一個參考,你跳出了這個法則,也不會有人判你刑,項目也未必會失敗,這就 需要大家使用的是考慮如何度量法則了。(轉自24種設計模式)


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 龙山县| 开封市| 漳州市| 巧家县| 中西区| 宜章县| 额济纳旗| 莱阳市| 潮安县| 噶尔县| 高州市| 衡水市| 康定县| 类乌齐县| 苗栗市| 玉环县| 临漳县| 莱阳市| 高邑县| 兰西县| 合江县| 浠水县| 平度市| 集安市| 牡丹江市| 安多县| 铁力市| 巫溪县| 孝感市| 晋江市| 洛扎县| 明溪县| 灵台县| 垦利县| 夹江县| 三明市| 镇沅| 新竹县| 崇阳县| 伊宁市| 景泰县|