迪米特法则
oldbirds
# 迪米特法则
迪米特法则(Law of Demeter,LOD),有时候也叫做最少知识原则(Least Knowledge Principle,LKP),它的定义是:一个软件实体应当尽可能少地与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类(中间类或者跳转类)来转达。
# 迪米特法则的规则
- Only talk to your immediate friends(只与直接的朋友通讯),一个对象的"朋友"包括他本身(self)、它持有的成员对象、入参对象、它所创建的对象。
- 尽量少发布 public 的变量和方法,一旦公开的属性和方法越多,修改的时候影响的范围越大。
- “是自己的就是自己的”,如果一个方法放在本类中,既不产生新的类间依赖,也不造成负面的影响,那么次方法就应该放在本类中。
# 迪米特法则的意义
迪米特法则的核心观念就是类间解耦,也就降低类之间的耦合,只有类处于弱耦合状态,类的复用率才会提高。所谓降低类间耦合,实际上就是尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。但是这样会引发一个问题,有可能产生大量的中间类或者跳转类,导致系统的复杂性提高,可维护性降低。如果一味追求极度解耦,那么最终有可能变成面向字节码编程甚至是面向二进制的 0 和 1 编程。
举个很简单的例子,体育老师要知道班里面女生的人数,他委托体育课代表点清女生的人数:
class Girl {}
class GroupLeader {
private var girls: [Girl]
init(girls: [Girl]) {
self.girls = girls
}
func countGirls() -> Int {
self.girls.count
}
}
class Teacher {
func command(leader: GroupLeader) {
leader.countGirls()
}
}
let teacher: Teacher = Teacher()
let groupLeader: GroupLeader = GroupLeader(girls: [Girl(), Girl()])
teacher.command(leader: groupLeader)
这个例子中,体育课代表就是中间类,体育课代表对于体育老师来说就是"直接的朋友",如果去掉体育课代表这个中间类,体育老师必须亲自清点女生的人数(实际上就数人数这个功能,体育老师是不必要获取所有女生的对象列表),这样做会违反迪米特法则。