前言
迪米特法則,聽名字有點奇怪,但是這個法則真的非常非常有意思,在我看來,這個法則其實描述的就是一個矜持的小姑娘,害羞的惹人憐愛。但是啊,姑娘雖好,切不可"貪杯"哦~
基本介紹
- 一個物件應該對其他物件保持最少的瞭解。
- 類與類關係越密切,耦合度越大
- 一個類對自己依賴的類知道的越少越好。也就是說,對於被依賴的類不管多麼複雜,都儘量將邏輯封裝在類的內部。對外除了提供的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的方法,總公司直接呼叫來列印,從而避免了與分公司的員工發生耦合。
總結
雖然說矜持害羞的姑娘惹人憐愛,但是我相信在座的各位碼狼們一定會特別的苦惱,因為很多簡單的事卻變得不那麼簡單直接。在你發起進攻的時候往往會給你當頭一棒。
所以啊,如果我們要遵循迪米特法則,也要根據我們的業務場景合理設計,反覆權衡,既做到結構清晰,又要高內聚低耦合。不要過分的迷戀這個矜持的小姑娘,否則簡單直接的事也會變得非常的麻煩。