設計模式的七大原則(6) --迪米特法則
- 2019 年 10 月 3 日
- 筆記
前言
迪米特法則,聽名字有點奇怪,但是這個法則真的非常非常有意思,在我看來,這個法則其實描述的就是一個矜持的小姑娘,害羞的惹人憐愛。但是啊,姑娘雖好,切不可"貪杯"哦~
基本介紹
- 一個對象應該對其他對象保持最少的了解。
- 類與類關係越密切,耦合度越大
- 一個類對自己依賴的類知道的越少越好。也就是說,對於被依賴的類不管多麼複雜,都盡量將邏輯封裝在類的內部。對外除了提供的public 方法,不對外泄露任何資訊
- 迪米特法則還有個更簡單的定義:只與直接(熟悉)的朋友通訊
- 直接(熟悉)的朋友:每個對象都會與其他對象有耦合關係,只要兩個對象之間有耦合關係, 我們就說這兩個對象之間是朋友關係。耦合的方式很多,依賴,關聯,組合,聚合等。
其中,我們稱出現成員變數,方法參數,方法返回值中的類為直接的朋友,而出現在局部變數中的類不是直接的朋友。也就是說,陌生的類最好不要以局部變數 的形式出現在類的內部。
把上面的概念一一翻譯成人話就是:
- 我們這個類姑娘啊,因為太矜持了不善於社交,所以對其他類夥伴們不怎麼熟悉。
- 類姑娘實在是太害羞了,一旦與別人多說幾句話就會緊張的不知所措,頻頻犯錯。
- 矜持的類姑娘儘管心思很活躍,愛多想。但是給別人的感覺都是純潔的像一張白紙。
- 因為類姑娘太過於矜持,害怕陌生人,認為陌生人都是壞人,所以只與自己熟悉的朋友交流。
- 類姑娘熟悉的朋友有:成員變數,方法參數,方法返回值的對象。而出現在其他地方的類都是陌生人,壞人!本姑娘拒絕與你交流!!!
哈哈,這樣應該大家都能理解了。總而言之就一句話:一個類應該盡量不要知道其他類太多的東西,不要和陌生的類有太多接觸。
案例
//總公司員工 class Employee{ private String id; public void setId(String id){ this.id = id; } public String getId(){ return id; } } //分公司員工 class SubEmployee{ private String id; public void setId(String id){ this.id = id; } public String getId(){ return id; } } class SubCompanyManager{ public List<SubEmployee> getAllEmployee(){ List<SubEmployee> list = new ArrayList<SubEmployee>(); for(int i=0; i<100; i++){ SubEmployee emp = new SubEmployee(); //為分公司人員按順序分配一個ID emp.setId("分公司"+i); list.add(emp); } return list; } } class CompanyManager{ public List<Employee> getAllEmployee(){ List<Employee> list = new ArrayList<Employee>(); for(int i=0; i<30; i++){ Employee emp = new Employee(); //為總公司人員按順序分配一個ID emp.setId("總公司"+i); list.add(emp); } return list; } public void printAllEmployee(SubCompanyManager sub){ List<SubEmployee> list1 = sub.getAllEmployee(); for(SubEmployee e:list1){ System.out.println(e.getId()); } List<Employee> list2 = this.getAllEmployee(); for(Employee e:list2){ System.out.println(e.getId()); } } } public class Client{ public static void main(String[] args){ CompanyManager e = new CompanyManager(); e.printAllEmployee(new SubCompanyManager()); } } 現在這個設計的主要問題出在CompanyManager中,根據迪米特法則,只與直接的朋友發生通訊,而SubEmployee類並不是CompanyManager類的直接朋友(以局部變數出現的耦合不屬於直接朋友),從邏輯上講總公司只與他的分公司耦合就行了,與分公司的員工並沒有任何聯繫,這樣設計顯然是增加了不必要的耦合。按照迪米特法則,應該避免類中出現這樣非直接朋友關係的耦合。修改後的程式碼如下:
class SubCompanyManager{ public List<SubEmployee> getAllEmployee(){ List<SubEmployee> list = new ArrayList<SubEmployee>(); for(int i=0; i<100; i++){ SubEmployee emp = new SubEmployee(); //為分公司人員按順序分配一個ID emp.setId("分公司"+i); list.add(emp); } return list; } public void printEmployee(){ List<SubEmployee> list = this.getAllEmployee(); for(SubEmployee e:list){ System.out.println(e.getId()); } } } class CompanyManager{ public List<Employee> getAllEmployee(){ List<Employee> list = new ArrayList<Employee>(); for(int i=0; i<30; i++){ Employee emp = new Employee(); //為總公司人員按順序分配一個ID emp.setId("總公司"+i); list.add(emp); } return list; } public void printAllEmployee(SubCompanyManager sub){ sub.printEmployee(); List<Employee> list2 = this.getAllEmployee(); for(Employee e:list2){ System.out.println(e.getId()); } } } 修改後,為分公司增加了列印人員ID的方法,總公司直接調用來列印,從而避免了與分公司的員工發生耦合。
總結
雖然說矜持害羞的姑娘惹人憐愛,但是我相信在座的各位碼狼們一定會特別的苦惱,因為很多簡單的事卻變得不那麼簡單直接。在你發起進攻的時候往往會給你當頭一棒。
所以啊,如果我們要遵循迪米特法則,也要根據我們的業務場景合理設計,反覆權衡,既做到結構清晰,又要高內聚低耦合。不要過分的迷戀這個矜持的小姑娘,否則簡單直接的事也會變得非常的麻煩。