最少知识原则(Least Knowledge Principle)
最少知识原则(Least Knowledge Principle),或者称迪米特法则(Law of Demeter),是一种面向对象程序设计的指导原则,它描述了一种保持代码松耦合的策略。其可简单的归纳为:
Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
每个单元对其他单元只拥有有限的知识,只了解与当前单元紧密联系的单元;
再简洁些:
Each unit should only talk to its friends; don't talk to strangers.
每个单元只能和它的 "朋友" 交谈,不能和 "陌生人" 交谈;
更简洁些:
Only talk to your immediate friends.
只和自己直接的 "朋友" 交谈。
应用到面向对象的程序设计中时,可描述为 "类应该与其协作类进行交互但无需了解它们的内部结构"。
A class should interact directly with its collaborators and be shielded from understanding their internal structure.
迪米特法则(Law of Demeter)由 Northeastern University 的 Ian Holland 在 1987 年提出,"Law of Demeter" 名称是来自当时正在进行的一项研究 "The Demeter Project"。
Demeter = Greek Goddess of Agriculture; grow software in small steps.
在 2004 年,Karl Lieberherr 在其论文 "Controlling the Complexity of Software Designs" 中将 LoD 的定义由 "Only talk to your friends" 改进为:
Only talk to your friends who share your concerns.
改进后的原则称为 LoDC(Law of Demeter for Concerns),它为软件设计带来了两个主要的益处:
It leads to better information hiding.
It leads to less information overload.
即,更好的信息隐藏和更少的信息重载。LoDC 原则在面向方面的软件开发(AOSD:Aspect-Oriented Software Development)中有着良好的应用。
最少知识原则在面向对象编程中的应用
在 "Law of Demeter" 应用于面向对象编程中时,可以简称为 "LoD-F:Law of Demeter for Functions/Methods"。
对于对象 O 中的一个方法 m ,m 方法仅能访问如下这些类型的对象:
- O 对象自身;
- m 方法的参数对象;
- 任何在 m 方法内创建的对象;
- O 对象直接依赖的对象;
具体点儿就是,对象应尽可能地避免调用由另一个方法返回的对象的方法。
现代面向对象程序设计语言通常使用 "." 作为访问标识,LoD 可以被简化为 "仅使用一个点(use only one dot)"。也就是说,代码 a.b.Method() 违反了 LoD,而 a.Method() 则符合 LoD。打个比方,人可以命令一条狗行走,但是不应该直接指挥狗的腿行走,应该由狗去指挥它的腿行走。
你是否见过类似下面这样儿的代码?
public Emailer(Server server) {…} // taking a server in the constructor
public void sendSupportEmail(String message, String toAddress) {
EmailSystem emailSystem = server.getEmailSystem();
String fromAddress = emailSystem.getFromAddress();
emailSystem.getSenderSubsystem().send(fromAddress, toAddress, message);
}
上面这个设计有几点问题:
- 复杂而且看起来不必要。Emailer 与多个它可能不是真的需要的 API 进行交互,例如 EmailSystem。
- 依赖于 Server 和 EmailSystem 的内部结构,如果两者之一进行了修改,则 Emailer 有可能被破坏。
- 不能重用。任何其他的 Server 实现也必须包含一个能返回 EmailSystem 的 API。
除了上面这几个问题之外,还有一个问题是这段代码是可测试的吗?你可能会说肯定可测啊,因为这个类使用了依赖注入(Dependency Injection),我们可以模拟 Server、EmailSystem 和 Sender 类。但真正的问题是,除了多出了这些模拟代码,任何对 API 的修改都将破坏所有的测试用例,使得设计和测试都变得非常脆弱。
解决上述问题的办法就是应用最少知识原则,仅通过构造函数注入直接依赖的对象。Emailer 无需了解是否 Server 类包含了一个 EmailSystem,也不知道 EmailSystem 包含了一个 Sender。
public Emailer(Sender sender, String fromAddress) {…}
public void sendSupportEmail(String message, String toAddress) {
sender.send(fromAddress, toAddress, message);
}
这个设计较为合理些。现在 Emailer 不再依赖 Server 和 EmailSystem,而是通过构造函数得到了所有的依赖项。同时 Emailer 也变得更容易理解,因为所有与其交互的对象都显式的呈现出来。
Emailer 与 Server 和 EmailSystem 也达到了解耦合的效果。Emailer 不再需要了解 Server 和 EmailSystem 的内部结构,任何对 Server 和 EmailSystem 的修改都不再会影响 Emailer。
而且,Emailer 的变得更易被复用。如果切换到另外一个环境中时,仅需实现一个不同的 Sender 即可。
对于测试而言,现在我们仅需模拟 Sender 依赖即可。
应用最少知识原则优点和缺点
优点:遵守 Law of Demeter 将降低模块间的耦合,提升了软件的可维护性和可重用性。
缺点:应用 Law of Demeter 可能会导致不得不在类中设计出很多用于中转的包装方法(Wrapper Method),这会提升类设计的复杂度。
面向对象设计的原则
SRP | ||
OCP | ||
LSP | ||
ISP |
||
DIP | ||
LKP |
参考资料
- Principle of Least Knowledge
- Demeter: Aspect-Oriented Software Development
- Law of Demeter
- Controlling the Complexity of Software Designs
- Introducing Demeter and its Laws
- The Paperboy, The Wallet, and The Law Of Demeter
- Principle of Least Knowledge
- Loose Coupling with Demeter
- An Empirical Validation of the Benefits of Adhering to the Law of Demeter
本文《最少知识原则(Least Knowledge Principle)》由 Dennis Gao 原创并发表自博客园,未经作者本人同意禁止任何形式的转载,任何自动或人为的爬虫行为均为耍流氓。
最少知识原则(Least Knowledge Principle)的更多相关文章
- 北风设计模式课程---最少知识原则(Least Knowledge Principle)
北风设计模式课程---最少知识原则(Least Knowledge Principle) 一.总结 一句话总结: 最少知识原则(Least Knowledge Principle),或者称迪米特法则( ...
- 设计模式值六大原则——迪米特法则(LoD)也称为最少知识原则(LKP)。
定义: 迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP). 一个对象应该对其他对象有最少的了解.通俗地讲,一个类应该对 ...
- 设计模式之迪米特原则(LOD)(最少知识原则)
来源:迪米特法则(LoD)最初是用来作为面向对象的系统设计风格的一种法则,是很多著名系统,如火星登陆软件系统.木星的欧罗巴卫星轨道飞船的软件系统的指导设计原则. 迪米特法则(LoD)又可分为两种:狭义 ...
- [Python设计模式] 第11章 迪米特法则——最少知识原则
github地址:https://github.com/cheesezh/python_design_patterns 迪米特法则 迪米特法则(LoD),也叫最少知识原则,如果两个类不必彼此直接通信, ...
- Java设计模式之外观模式和最少知识原则
外观模式: 外观模式:提供一个统一的接口,来访问子系统中一群功能相关接口(类似一键启动,一键关闭等等) 外观模式定义了一个高层接口,让子系统更容易使用 降低对外接口耦合度 外观模式和命令模式各自侧重点 ...
- 迪米特法则(LoD),即最少知识原则
解释: 如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用.如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用. 重点: 在类的结构上,每个类都应当尽量降低成员 ...
- 设计模式-设计原则(Design Principle)
本文由@呆代待殆原创,转载请注明出处. 写在前面:所谓设计原则并不是一定要遵守的法则,只是一种建议,因为保持这些原则本身会有一定代价,若是这些代价超过了带来的好处就得不偿失了,所以一切还是以简单为准. ...
- 命令查询分离原则Command-query separation principle
在UML和模式应用一书中,发送给Die的roll消息之后跟随着第二个消息getFaceValue用于提取其新的faceValue,特别是:roll()方法是void的,没有返回值,例如: public ...
- 面象对象设计原则之一:单一职责原则(Single Responsibility Principle, SRP)
单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小.单一职责原则定义如下:单一职责原则(Single Responsibility Principle, SRP):一个类只负责一个功能领域 ...
随机推荐
- oracle 11gr2 官方文档下载
http://www.oracle.com/technetwork/database/enterprise-edition/documentation/index.html
- 给angularJs的service建模
先回顾一下我们遇到的问题: 通过一个dialogService创建对话框,并将该service的参数数据通过resolve的方式传递给对话框的controller. controller解析数据后放置 ...
- winform初学
一.建立winform工程项目
- C#获取当前路径的7种方法
总结C#获取当前路径的7种方法 C#获取当前路径的方法如下: 1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName ...
- 脚本tips
脚本中所有的命令都要echo到log文件里,方便跟踪. grep的时候要小心grep出多行,正则表达式的匹配越精确越好!
- Linux三剑客之awk
awk awk是linux下的一个命令,他对其他命令的输出,对文件的处理都十分强大,其实他更像一门编程语言,他可以自定义变量,有条件语句,有循环,有数组,有正则,有函数等.他读取输出,或者文件的方式是 ...
- 《uml大战需求分析》阅读笔记05
<uml大战需求分析>阅读笔记05 这次我主要阅读了这本书的第九十章,通过看这章的知识了解了不少的知识开发某系统的重要前提是:这个系统有谁在用?这些人通过这个系统能做什么事? 一般搞清楚这 ...
- Linux 如何使用压缩与解压缩的方式将Windows下的zip压缩包上传到Linux系统
当我们无法使用xftp方式上传文件到Linux系统时,我们可以使用在Windows下压缩文件夹,然后到Linux系统下解压缩的方式,完成整个上传工作. 第一步:在Windows系统下,将整个文件夹压缩 ...
- mha报错
用命令检查集群复制状态:masterha_check_repl --conf=/etc/masterha/app1.cnf 报错如下: Tue Jan 12 09:25:51 2016 - [info ...
- block的复习
main.m // // main.m // 8A10.Block的复习 // // Created by huan on 16/2/8. // Copyright © 2016年 huanx ...