迪米特法则

110 阅读3分钟

迪米特法则

迪米特法则(Law of Demeter,LoD)

核心思想:一个软件实体应当尽可能少的与其他实体发生相互作用。只和直接(亲近)的朋友说话,不和陌生人说话。

一个类对自己依赖的类知道的越少越好,只需要和直接的对象进行交互,而不用在乎这个对象的内部组成结构。

案例分析:

案例一:

如类 A 中有类B的对象;类 B 中有类 C 的对象,调用方有一个类 A 的对象 a,这时要访问 C 对象的属性,不要采用类似下面的写法:

a.getB().getC().getProperties()

而应该是:

a.getCProperties()

至于 getCProperties 怎么实现是类 A 要负责的事情,我只和我直接的对象 a 进行交互,不访问我不了解的对象。

案例二:

动物园内种类繁多,有鸟类馆、熊猫馆。假设某国外领导人来访华,参观动物园,他想知道动物园内叫“贝贝”大熊猫年龄多大,体重多少。他难道要先去调取熊猫馆的信息,再去查找叫“贝贝”的这只大熊猫,再去看他的信息吗?显然不用,他只要问一下动物园的馆长就可以了。动物园的馆长会告诉他所有需要的信息,因为他只认识动物园的馆长,并不了解动物园的内部结构,也不需要去了解。

zooAdmin.getPandaBeiBeiInfo()

案例三:

假设我们有一个学校系统,其中包括SchoolTeacherStudent类。在不遵循迪米特法则的设计中,如果想要让学校打印出所有学生的姓名,可能会设计成学校直接遍历老师和学生:

class Student {
  private name: string
​
  constructor(name: string) {
    this.name = name
  }
​
  public getName(): string {
    return this.name
  }
}
​
class Teacher {
  private students: Student[]
​
  constructor(students: Student[]) {
    this.students = students
  }
​
  public getStudents() {
    return this.students
  }
}
​
class School {
  private teachers: Teacher[]
​
  constructor(teachers: Teacher[]) {
    this.teachers = teachers
  }
​
  public printAllStudentNames(): void {
    this.teachers.forEach(teacher => {
      teacher.getStudents().forEach(student => {
        console.log(student.getName())
      })
    })
  }
}
​
function test() {
  // 示例使用
  const students1 = [new Student('John'), new Student('Jane')]
  const teacher1 = new Teacher(students1)
  const students2 = [new Student('Mike'), new Student('Anna')]
  const teacher2 = new Teacher(students2)
  const school = new School([teacher1, teacher2])
  school.printAllStudentNames()
}
test()

在这个设计中,School类直接依赖于Teacher和Student类的内部实现(例如,School需要知道老师是如何存储学生的,以及如何获取学生的信息)。这种设计违反了迪米特法则,因为School类需要与非直接的朋友Student类进行交互。

遵循迪米特法则的设计应该尽量减少School对Teacher和Student内部实现的了解。可以让Teacher类提供一个打印所有学生姓名的方法,然后School类只需要调用每个Teacher的这个方法:

class Student {
  private name: string
​
  constructor(name: string) {
    this.name = name
  }
​
  public getName(): string {
    return this.name
  }
}
​
class Teacher {
  private students: Student[]
​
  constructor(students: Student[]) {
    this.students = students
  }
​
  public printStudentNames(): void {
    this.students.forEach(student => console.log(student.getName()))
  }
}
​
class School {
  private teachers: Teacher[]
​
  constructor(teachers: Teacher[]) {
    this.teachers = teachers
  }
​
  public printAllStudentNames(): void {
    this.teachers.forEach(teacher => teacher.printStudentNames())
  }
}
​
function test() {
  // 示例使用
  const students1 = [new Student('John'), new Student('Jane')]
  const teacher1 = new Teacher(students1)
  const students2 = [new Student('Mike'), new Student('Anna')]
  const teacher2 = new Teacher(students2)
  const school = new School([teacher1, teacher2])
  school.printAllStudentNames()
}
test()

参考:learn.lianglianglee.com/%e4%b8%93%e…