# 3.5 迪米特法则(最少知道原则)

# 3.5.1 介绍

迪米特法则(Demeter Principle)又叫最少知道原则,即一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

只和你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。

其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。

# 3.5.2 定义

  • 一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public方法,不对外泄露任何信息。

  • 一个对象应该对其他对象保持最少的了解,又被称为最少知道原则

  • 为了降低类与类之间的耦合关系

  • 强调只和朋友交流,不和陌生人说话

  • 朋友指的是成员变量/方法中输入或输出的参数

下面看一个例子来理解迪米特法则

【例】明星与经纪人的关系实例

明星由于全身心投入艺术,所以许多日常事务由经纪人负责处理,如和粉丝的见面会,和媒体公司的业务洽淡等。这里的经纪人是明星的朋友,而粉丝和媒体公司是陌生人,所以适合使用迪米特法则。

类图如下:

image-20191229173554296

代码如下:

明星类(Star)

public class Star {
    private String name;

    public Star(String name) {
        this.name=name;
    }

    public String getName() {
        return name;
    }
}
1
2
3
4
5
6
7
8
9
10
11

粉丝类(Fans)

public class Fans {
    private String name;

    public Fans(String name) {
        this.name=name;
    }

    public String getName() {
        return name;
    }
}
1
2
3
4
5
6
7
8
9
10
11

媒体公司类(Company)

public class Company {
    private String name;

    public Company(String name) {
        this.name=name;
    }

    public String getName() {
        return name;
    }
}
1
2
3
4
5
6
7
8
9
10
11

经纪人类(Agent)

public class Agent {
    private Star star;
    private Fans fans;
    private Company company;

    public void setStar(Star star) {
        this.star = star;
    }

    public void setFans(Fans fans) {
        this.fans = fans;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    public void meeting() {
        System.out.println(fans.getName() + "与明星" + star.getName() + "见面了。");
    }

    public void business() {
        System.out.println(company.getName() + "与明星" + star.getName() + "洽淡业务。");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 3.5.3 案例

# 3.5.3.1 案例介绍

  • 老板通知部门经理开会,部门经理通知工程师工作
  • 老板只做老板该做的事,只通知部门经理,部门经理再通知工程师,工程师工作

# 3.5.3.2 实现

  • 创建最顶层Human接口
public interface Human {
}
1
2
  • 创建抽象工程师对象,实现Human接口,并赋予工程师工作能力
public abstract class Programer implements Human{
    public abstract void work();
}
1
2
3
  • 创建java开发工程师
public class JavaProgramer extends Programer{
    @Override
    public void work() {
        System.out.println("Java程序员正在开发Java程序......");
    }
}

1
2
3
4
5
6
7
  • 创建python开发工程师
public class PythonProgramer extends Programer{
    @Override
    public void work() {
        System.out.println("Python程序员正在开发Python程序......");
    }
}
1
2
3
4
5
6
  • 创建管理层接口,实现Human接口
public interface Manager extends Human{

}
1
2
3
  • 创建老板对象,只有通知部门领导接口
public class Boss implements Manager{
    public void meet(TeamLeader teamLeader){
        System.out.println("老板开会,分布任务");
        teamLeader.assignTasks();
    }
}
1
2
3
4
5
6
  • 创建部门领导对象,只有通知工程师接口
public class TeamLeader implements Manager{
    private Programer[] programers;

    public TeamLeader(Programer... programer) {
        this.programers = programer;
    }

    public void assignTasks(){
        Arrays.stream(programers).forEach(programer ->{
            if(programer instanceof JavaProgramer){
                System.out.println("给java开发工程师分配任务");
            }else {
                System.out.println("给python开发工程师分配任务");
            }
            programer.work();
        });
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  • 创建测试类
public class Test {
    public static void main(String[] args) {
        Boss boss = new Boss();
        TeamLeader teamLeader = new TeamLeader(new JavaProgramer(),new PythonProgramer());
        boss.meet(teamLeader);
    }
}
1
2
3
4
5
6
7
上次更新: 2024/4/13