最少知道原则

迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。

迪米特法则不希望类直接建立直接的接触。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系-这在一定程度上增加了系统的复杂度。

例如,购房者要购买楼盘A、B、C中的楼,他不必直接到楼盘去买楼,而是可以通过一个售楼处去了解情况,这样就减少了购房者与楼盘之间的耦合,如图10-6所示,。

最少知道原则_第1张图片

 

举另一个例子:有一个集团公司,下属单位有分公司和直属部门,现在要求打印出所有下属单位的员工ID。先来看一下违反迪米特法则的设计。

[java] view plain copy

  1. //总公司员工  
  2. class Employee{  
  3.     private String id;  
  4.     public void setId(String id){  
  5.         this.id = id;  
  6.     }  
  7.     public String getId(){  
  8.         return id;  
  9.     }  
  10. }  
  11.   
  12. //分公司员工  
  13. class SubEmployee{  
  14.     private String id;  
  15.     public void setId(String id){  
  16.         this.id = id;  
  17.     }  
  18.     public String getId(){  
  19.         return id;  
  20.     }  
  21. }  
  22.   
  23. class SubCompanyManager{  
  24.     public List getAllEmployee(){  
  25.         List list = new ArrayList();  
  26.         for(int i=0; i<100; i++){  
  27.             SubEmployee emp = new SubEmployee();  
  28.             //为分公司人员按顺序分配一个ID  
  29.             emp.setId("分公司"+i);  
  30.             list.add(emp);  
  31.         }  
  32.         return list;  
  33.     }  
  34. }  
  35.   
  36. class CompanyManager{  
  37.   
  38.     public List getAllEmployee(){  
  39.         List list = new ArrayList();  
  40.         for(int i=0; i<30; i++){  
  41.             Employee emp = new Employee();  
  42.             //为总公司人员按顺序分配一个ID  
  43.             emp.setId("总公司"+i);  
  44.             list.add(emp);  
  45.         }  
  46.         return list;  
  47.     }  
  48.       
  49.     public void printAllEmployee(SubCompanyManager sub){  
  50.         List list1 = sub.getAllEmployee();  
  51.         for(SubEmployee e:list1){  
  52.             System.out.println(e.getId());  
  53.         }  
  54.   
  55.         List list2 = this.getAllEmployee();  
  56.         for(Employee e:list2){  
  57.             System.out.println(e.getId());  
  58.         }  
  59.     }  
  60. }  
  61.   
  62. public class Client{  
  63.     public static void main(String[] args){  
  64.         CompanyManager e = new CompanyManager();  
  65.         e.printAllEmployee(new SubCompanyManager());  
  66.     }  
  67. }  

        现在这个设计的主要问题出在CompanyManager中,根据迪米特法则,只与直接的朋友发生通信,而SubEmployee类并不是CompanyManager类的直接朋友(以局部变量出现的耦合不属于直接朋友),从逻辑上讲总公司只与他的分公司耦合就行了,与分公司的员工并没有任何联系,这样设计显然是增加了不必要的耦合。按照迪米特法则,应该避免类中出现这样非直接朋友关系的耦合。修改后的代码如下:

public class MainEmployee {
    // 母公司员工ID
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}

 

[java] view plain copy

  1. public class MainCompanyManager {
        // 得到母公司员工信息
        public List getAllMainEmployee(){
            List list = new ArrayList();
            for(int i=0; i<30; i++){
                MainEmployee emp = new MainEmployee();
                //为总公司人员按顺序分配一个ID
                emp.setId("总公司"+i);
                list.add(emp);
            }
            return list;
        }
        // 打印母公司所有员工信息
        public void printMainEmployee(){
             List list2 = this.getAllMainEmployee();
             for(MainEmployee e:list2){
                 System.out.println(e.getId());
             }
        }
        // 打印母公司与子公司所有员工信息
        public void printAllEmployee(SubCompanyManager sub){
            sub.printSubEmployee();
            this.printMainEmployee();

        }

    }

    public class SubEmployee {
        // 子公司员工ID
        private String id;
        public void setId(String id){
            this.id = id;
        }
        public String getId(){
            return id;
        }
    }

       

import java.util.List;

public class SubCompanyManager {
    // 得到子公司所有员工信息
    public List getAllSubEmployee(){
        List list = new ArrayList();
        for(int i=0; i<100; i++){
            SubEmployee emp = new SubEmployee();
            //为子公司人员按顺序分配一个ID
            emp.setId("分公司"+i);
            list.add(emp);
        }
        return list;
    }
    // 打印子公司所有员工信息
    public void printSubEmployee(){
        List list = this.getAllSubEmployee();
        for(SubEmployee e:list){
            System.out.println(e.getId());
        }
    }

}

 

修改后,为分公司增加了打印人员ID的方法,总公司直接调用来打印,从而避免了与分公司的员工发生耦合。

 

        迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,例如本例中,总公司就是通过分公司这个“中介”来与分公司的员工发生联系的。过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合。

 

你可能感兴趣的:(设计模式)