設計模式的七大原則(6) --迪米特法則

  • 2019 年 10 月 3 日
  • 筆記

前言

迪米特法則,聽名字有點奇怪,但是這個法則真的非常非常有意思,在我看來,這個法則其實描述的就是一個矜持的小姑娘,害羞的惹人憐愛。但是啊,姑娘雖好,切不可"貪杯"哦~

基本介紹

  1. 一個對象應該對其他對象保持最少的了解。
  2. 類與類關係越密切,耦合度越大
  3. 一個類對自己依賴的類知道的越少越好。也就是說,對於被依賴的類不管多麼複雜,都盡量將邏輯封裝在類的內部。對外除了提供的public 方法,不對外泄露任何資訊
  4. 迪米特法則還有個更簡單的定義:只與直接(熟悉)的朋友通訊
  5. 直接(熟悉)的朋友:每個對象都會與其他對象有耦合關係,只要兩個對象之間有耦合關係, 我們就說這兩個對象之間是朋友關係。耦合的方式很多,依賴,關聯,組合,聚合等。
    其中,我們稱出現成員變數,方法參數,方法返回值中的類為直接的朋友,而出現在局部變數中的類不是直接的朋友。也就是說,陌生的類最好不要以局部變數 的形式出現在類的內部。

把上面的概念一一翻譯成人話就是:

  1. 我們這個類姑娘啊,因為太矜持了不善於社交,所以對其他類夥伴們不怎麼熟悉。
  2. 類姑娘實在是太害羞了,一旦與別人多說幾句話就會緊張的不知所措,頻頻犯錯。
  3. 矜持的類姑娘儘管心思很活躍,愛多想。但是給別人的感覺都是純潔的像一張白紙。
  4. 因為類姑娘太過於矜持,害怕陌生人,認為陌生人都是壞人,所以只與自己熟悉的朋友交流。
  5. 類姑娘熟悉的朋友有:成員變數,方法參數,方法返回值的對象。而出現在其他地方的類都是陌生人,壞人!本姑娘拒絕與你交流!!!

哈哈,這樣應該大家都能理解了。總而言之就一句話:一個類應該盡量不要知道其他類太多的東西,不要和陌生的類有太多接觸。

案例

//總公司員工  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的方法,總公司直接調用來列印,從而避免了與分公司的員工發生耦合。

總結

雖然說矜持害羞的姑娘惹人憐愛,但是我相信在座的各位碼狼們一定會特別的苦惱,因為很多簡單的事卻變得不那麼簡單直接。在你發起進攻的時候往往會給你當頭一棒。

所以啊,如果我們要遵循迪米特法則,也要根據我們的業務場景合理設計,反覆權衡,既做到結構清晰,又要高內聚低耦合。不要過分的迷戀這個矜持的小姑娘,否則簡單直接的事也會變得非常的麻煩。

Tags: