当前位置:网站首页>迪米特法则
迪米特法则
2022-06-27 10:05:00 【华为云】
什么是迪米特法则
迪米特法则(Law of Demeter, LoD),又被称为最少知识原则,这个原则规定了,一个对象应该对另一个对象有最少的了解,什么又是最少的了解,就是减少一个对象在另一个对象出现的次数,甚至不出现,减少类于类之间的耦合关系。
一个类对另一个类的了解,都是基于其public方法。
迪米特法则还有一个英文解释:Only talk to your immediate friends,只于一个类之间的朋友进行交流。
什么是类于类之间的交流?无非就是一个类中的方法中调用另一个类的方法。
什么是直接朋友?一个类的朋友就是这个类本身、这个类的成员对象、这个对象创建的对象、当前对象的方法参数等等。
参考如下代码,Address,Book,Stuent这些都是Teacher的朋友。
public class Teacher { private Address address; public void tech(Book book){ System.out.println(book.getName); } public Studnet findStudent(){ return Student(); }}只和朋友交流
如何做到之和朋友类交流,来看一个案例:
老师想让班长去清点一下班级的人数,让我们用代码去实现这个场景;
先看类图:
代码:
public class Student {}public class Teacher { void command(Monitor monitor){ List<Student> listStudent = new ArrayList<>(); for (int i=0; i<3; i++){ listStudent.add(new Student()); } monitor.countStudent(listStudent); }}public class Monitor { void countStudent(List<Student> list){ System.out.println("学生人数:" + list.size()); }}public class Client { public static void main(String[] args) { Teacher teacher = new Teacher(); teacher.command(new Monitor()); }}运行结果:
运行结果很成功,学生人数被统计出来了。
但是这样的设计有什么问题?
首先Teacher类有几个朋友类,只有Monitor类(成员变量),那这里Student类是它的朋友类吗?不是,Student类是在方法中产生的,不是朋友类,但它却出现在了Teacher类中,这就相当于和Teacher类产生了交流,产生了依赖,这样回导致,如果以后Student类发生了改变,Teacher类也得同步参数修改,这是严重不允许的,严重违反迪米特法则。
让我们去修改一下这个类图结构:

public class Student {}public class Monitor { private List<Student> list; public Monitor(List<Student> list) { this.list = list; } void countStudent(){ System.out.println("学生人数:" + list.size()); }}public class Teacher { void command(Monitor monitor){ monitor.countStudent(); }}public class Client { public static void main(String[] args) { Teacher teacher = new Teacher(); List<Student> listStudent = new ArrayList<>(); for (int i=0; i<3; i++){ listStudent.add(new Student()); } teacher.command(new Monitor(listStudent)); }}观察改进前和改进后的代码有什么区别,改进前,Monitor类需要统计Student类,需要一个List,通过它的上级调用类,也就是Teacher类创建得到,虽然完成了业务,但是却导致Teacher类和它的非朋友类Student产生了交流,以后如果Student类有改动,Teacher类也会跟着改,于是进行修改,把Monitor类和Studnet类的依赖用成员变量的方式进行依赖,通过构造方法进行传递,这样Teacher类就可以不用和Studnet类进行交流,就能完成业务了。
朋友之间交流也不要太密切
迪米特法则中规定,一个类中,只与这个类的朋友进行联系,说简单点,就是一个类的方法中,如果一个类不是这个类的成员变量、函数参数、或者这个类通过方法创建出来的,最好不要出现在这个方法中。
但是,即使这个某个类是这个类的朋友,也应该尽可能的减少交流,也就是调用。
比如说,我们的电脑要安装一个软件,是不是要点击软件包,然后一直点下一步,如果某一步失败,后续的步骤也不能继续往下执行了。
来用代码表示是什么样的?
public class Install { int checkDir(){ System.out.println("检查目录"); return 1; } int checkSpace(){ System.out.println("检查空间"); return 1; } int install(){ System.out.println("安装软件"); return 1; }}public class Computer { private Install install; public Computer(Install install) { this.install = install; } void installSoftWare(){ //检查目录是否存在 int i = install.checkDir(); if (i==1){ //检查空间是否足够 int i1 = install.checkSpace(); if (i1==1){ int install = this.install.install(); if (install==1){ System.out.println("安装成功"); return; }else { System.out.println("安装失败"); return; } } } System.out.println("安装失败"); }}仔细看Computer类安装的方法,它和之间的朋友类Install进行交流,每次步骤返回1,代表成功,就进行下一步。这样的代码也许能模拟这个业务,但是它有什么问题?我们得考虑以后代码变动的风险,如果以后,每个安装步骤的返回值,不在返回1代表成功,而是布尔类型的true代表成功,这样回导致Computer类所有对这些方法调用的地方都得修改。
为了改进这种情况,我们需要对类结构进行修改,如下:
public class Install { private int checkDir(){ System.out.println("检查目录"); return 1; } private int checkSpace(){ System.out.println("检查空间"); return 1; } private int install(){ System.out.println("安装软件"); return 1; } public void installSoftForComputer(){ int i = checkDir(); if (i==1){ //检查空间是否足够 int i1 = checkSpace(); if (i1==1){ int install = install(); if (install==1){ System.out.println("安装成功"); return; }else { System.out.println("安装失败"); return; } } } System.out.println("安装失败"); }}public class Computer { private Install install; public Computer(Install install) { this.install = install; } void installSoftWare(){ //检查目录是否存在 install.installSoftForComputer(); }}看到改变前后的区别了吗?我把之前computer需要一个一个去调用的方法,封装在了Install一个public方法中,并且把每个安装步骤都设置为私有,这样有什么好处?我们减少了类与类之间的交流,同时也减少了它们变更带了的风险,以后Install类的变更,比如变更返回类型,那也只对Install内部有影响,这就是我们常说的高内聚!
边栏推荐
- es 根据索引名称和索引字段更新值
- . Net
- 一次线上移动端报表网络连接失败问题定位与解决
- 【OpenCV 例程200篇】212. 绘制倾斜的矩形
- [STM32] Hal library stm32cubemx tutorial 12 - IIC (read AT24C02)
- [hcie-rs review mind map] - STP
- Curiosity mechanism in reinforcement learning
- 测试同学怎么参与codereview
- js 所有的网络请求方式
- [so official interview] Why do developers using rust love it so much
猜你喜欢

【HCIE-RS复习思维导图】- STP

小哥凭“量子速读”绝技吸粉59万:看街景图0.1秒,“啪的一下”在世界地图精准找到!...

邮件系统(基于SMTP协议和POP3协议-C语言实现)

产品力对标海豹/Model 3,长安深蓝SL03预售17.98万起

Explain the imaging principle of various optical instruments in detail

Tdengine invitation: be a superhero who uses technology to change the world and become TD hero

Es update values based on Index Names and index fields

Use aspese slides to convert PPT to PDF

通俗易懂理解樸素貝葉斯分類的拉普拉斯平滑

你睡觉时大脑真在自动学习!首个人体实验证据来了:加速1-4倍重放,深度睡眠阶段效果最好...
随机推荐
C语言学习-Day_04
vector::data() 指针使用细节
R语言使用caret包的preProcess函数进行数据预处理:对所有的数据列进行center中心化(每个数据列减去平均值)、设置method参数为center
你睡觉时大脑真在自动学习!首个人体实验证据来了:加速1-4倍重放,深度睡眠阶段效果最好...
2021 CSP J2入门组 CSP-S2提高组 第2轮 视频与题解
R語言plotly可視化:可視化多個數據集歸一化直方圖(historgram)並在直方圖中添加密度曲線kde、設置不同的直方圖使用不同的分箱大小(bin size)、在直方圖的底部邊緣添加邊緣軸須圖
测试同学怎么参与codereview
For a moment, the ban of the US e-cigarette giant has been postponed, and products can be sold in the US for the time being
【OpenCV 例程200篇】211. 绘制垂直矩形
详解各种光学仪器成像原理
[hcie-rs review mind map] - STP
R语言plotly可视化:可视化多个数据集归一化直方图(historgram)并在直方图中添加密度曲线kde、设置不同的直方图使用不同的分箱大小(bin size)、在直方图的底部边缘添加边缘轴须图
Brother sucks 590000 fans with his unique "quantum speed reading" skill: look at the street view for 0.1 seconds, and "snap" can be accurately found on the world map
JS 文件上传下载
C语言学习-Day_05
12 necessary tools for network engineers
我大抵是卷上瘾了,横竖睡不着!竟让一个Bug,搞我两次!
border影响父元素的高度-解决方案
R language plot visualization: visualize the normalized histograms of multiple data sets, add density curve KDE to the histograms, set different histograms to use different bin sizes, and add edge whi
Use of bufferedwriter and BufferedReader