一文让你学会“迪米特法则”,不会你来找我!

986 阅读6分钟

说说闲话

工作本来就辛苦,学习当然要开心着进行了。开始正文前,先吐槽一件小事(跟本文技术点无关,可手动过滤掉)。

最近天气是越来越热了,雷雨天气也多了起来。最近这几天“菜鸟”这里一直是阴晴不定,雨是说来就来。

不过经过我多年的观察发现了这么一个现象:下雨的时间一般都集中在上下班的路上。这一发现让我很是困惑,是我备受雨水的青睐,还是它本身就是一个惯犯?

简介

创建史

迪米特法则是1987年秋天由美国Northeastern University的Ian Holland提出的。

基本概念

1、一个类对自己依赖的其它类知道的越少越好,为此迪米特法则又被称为“最少知道原则”。
2、迪米特有一个简单定义:talk only to your immediate friends(只和你的直接朋友交谈)。

存在的意义:

类与类之间知道的越多,关系就越密切,其耦合度就越大,代码就越不灵活。迪米特法则存在的意义就是为了降低类之间的耦合度。

以上就是迪米特法则的一些简单介绍,通过单纯的文字描述,可能大家对该原则的认知还不是特别清晰。不需要挠头,请接着向下看,我会详细为大家进行讲解。

最少知道原则

最少知道原则”的含义相信大家都明白。那如何能做到“最少知道”呢?大家可以先看下面的示例,并思考一下。

现在需要实现人进行洗衣服的功能。实现该功能我们需要两个类:一个表示人的类,具有洗衣服的方法。一个表示洗衣机的类,具有接收衣服、洗涤和烘干三个方法。

代表洗衣机的类:

public class WashingMachine {

  // 接收衣服的方法
  public void receiveClothes() {
    System.out.println("菜鸟牌洗衣机,开始接收衣服了!");
  }

  // 洗涤的方法
  public void wash() {
    System.out.println("菜鸟牌洗衣机,开始洗衣服了!");
  }

  // 烘干的方法
  public void drying() {
    System.out.println("菜鸟牌洗衣机,开始烘干衣服了!");
  }
}

代表人的类:

public class Person {

  // 使用洗衣机洗衣服的方法
  public void washClothes(WashingMachine washingMachine) {
    System.out.println("小菜鸟拿好衣服准备清洗。");
    washingMachine.receiveClothes();
    washingMachine.wash();
    washingMachine.drying();
  }

}

通过以上两个类就可以实现洗衣服的功能,但是这种实现是不符合“最少知道原则”的。大家能看出来是哪里吗?

其实很简单,相对于Person类来说,我们是要实现洗衣服的功能,具体洗衣机如何洗?我们是不需要了解的。但是上面Person类中的washClothes方法,却一连调用了WashingMachine类的三个方法。并且这三个方法都是洗衣机需要做的,跟我们人没有什么关系。这就造成了Person类对WashingMachine类知道的太多了。

解决该问题的方法也很简单,其根源是在本类自己,从根源上约束自己,尽量不暴露一些独属于自己的方法和属性。可以简单理解为,每个类都是要有属于自己的秘密。这样就可以使其它类对自己知道的更少。

根据以上分析,将上面的代码作出如下调整。

优化后的洗衣机类:

public class WashingMachine {

  // 自动洗衣
  public void automatic() {
    this.receiveClothes();
    this.wash();
    this.drying();
  }

  // 接收衣服的方法
  private void receiveClothes() {
    System.out.println("菜鸟牌洗衣机,开始接收衣服了!");
  }

  // 洗涤的方法
  private void wash() {
    System.out.println("菜鸟牌洗衣机,开始洗衣服了!");
  }

  // 烘干的方法
  private void drying() {
    System.out.println("菜鸟牌洗衣机,开始烘干衣服了!");
  }
}

优化后代表人的类:

public class Person {

  // 使用洗衣机洗衣服的方法
  public void washClothes(WashingMachine washingMachine) {
    System.out.println("小菜鸟拿好衣服准备清洗。");
    washingMachine.automatic();
  }

}

这就是“最少知道原则”,还挺简单的对吧。它就是告诉我们在创建类的时候将一些独属于自己的方法、属性,私有化在本类中。

和直接朋友交谈

我们称出现在成员变量,方法参数,方法返回值中的类为本类的直接朋友,而出现在局部变量中的类则不是直接朋友。交谈可以简单理解为使用其它类。此观点就是告诉我们尽量不要在本类中通过局部变量的形式使用其它陌生类。

为了加深印象,请看下列示例代码(该代码的功能是项目经理清点员工数量)。

程序员类:


public class Programmer {

  // 姓名
  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  // 获取程序员
  public List<Programmer> getProgrammers() {
    List<Programmer> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
      Programmer p = new Programmer();
      p.setName(i + "号码农");
      list.add(p);
    }
    return list;
  }
}

项目经理类:

public class ProjectManager {

  // 姓名
  private String name;

  // 构造方法
  ProjectManager(String name) {
    this.name = name;
  }

  // 清点员工数量
  public void countEmployees(){
    System.out.println(name + "开始清点程序员!");
    Programmer programmer = new Programmer();
    List<Programmer> list = programmer.getProgrammers();
    for (Programmer p : list) {
      System.out.println(p.getName());
    }
  }
}

测试类:

public class Demo {

  public static void main(String[] args) {
    ProjectManager projectManager = new ProjectManager("小菜鸟");
    projectManager.countEmployees();
  }
}

请看ProjectManagercountEmployees方法,该方法所使用的Programmer类是通过局部变量创建出来的,那么Programmer类就是一个陌生类。我们使用了陌生类,这是不符合“只和直接朋友交谈”的规则的。

我们可以按照“迪米特法则”将上面代码作出如下优化:

// 修改ProjectManager类的countEmployees方法
public void countEmployees(Programmer programmer){
    System.out.println(name + "开始清点程序员!");
    List<Programmer> list = programmer.getProgrammers();
    for (Programmer p : list) {
      System.out.println(p.getName());
    }
}

我们将Programmer类作为方法入参传递进来,这样Programmer类就是ProjectManager的“直接朋友”了。这样做我们的程序就符合“只和直接朋友交流”的规则了。

注意

迪米特法则是为了降低类之间(对象间)的耦合度,是为了减少不必要的依赖,并不是要求完全没有依赖关系。

我们使用时需要适度,而不是过分应用。完全独立的类,是没有存在的价值的,没有意义的。

今天的分享就到这里了,如果感觉“菜鸟”写的文章还不错,记得点赞关注呦!你们的支持就是我坚持下去的动力。

文章哪里写的有问题的也希望大家可以指出,我会虚心受教。如果有什么想要了解的知识也可以在评论区告诉我,有我了解的,我会为大家详细讲解。