当前位置:网站首页>迪米特法则
迪米特法则
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内部有影响,这就是我们常说的高内聚!
边栏推荐
- 谷歌浏览器 chropath插件
- CPU design (single cycle and pipeline)
- 如何获取GC(垃圾回收器)的STW(暂停)时间?
- 感应电机直接转矩控制系统的设计与仿真(运动控制matlab/simulink)
- On anchors in object detection
- Freemarker
- Arduino PROGMEM静态存储区的使用介绍
- Win10 shortcut key sorting
- C语言学习-Day_04
- This application failed to start because it could not find or load the QT platform plugin
猜你喜欢

Comparison between new and old interfaces

Multi thread implementation rewrites run (), how to inject and use mapper file to operate database

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

2-4Kali下安装nessus

oracle触发器 存储过程同时写入

【OpenCV 例程200篇】212. 绘制倾斜的矩形
Scientists develop two new methods to provide stronger security protection for intelligent devices

es 根据索引名称和索引字段更新值

C语言学习-Day_06
![文件名设置导致writelines写入报错:OSError: [Errno 22] Invalid argument](/img/08/2d4f425e6941af35616911672b6fed.png)
文件名设置导致writelines写入报错:OSError: [Errno 22] Invalid argument
随机推荐
Only one confirmcallback is supported by each rabbittemplate
如何获取GC(垃圾回收器)的STW(暂停)时间?
隐私计算FATE-离线预测
Es update values based on Index Names and index fields
我大抵是卷上瘾了,横竖睡不着!竟让一个Bug,搞我两次!
std::memory_ order_ seq_ CST memory order
多线程实现 重写run(),怎么注入使用mapper文件操作数据库
C language learning day_ 06
The R language uses the preprocess function of the caret package for data preprocessing: Center all data columns (subtract the average value from each data column), and set the method parameter to cen
js的数组拼接「建议收藏」
Location and solution of network connection failure of primary online mobile terminal Report
lvi-sam 总结
Explain the imaging principle of various optical instruments in detail
Record in detail the implementation of yolact instance segmentation ncnn
2-4 installation of Nessus under Kali
【HCIE-RS复习思维导图】- STP
Tdengine invitation: be a superhero who uses technology to change the world and become TD hero
有关WIN10的内存压缩
R langage plotly visualisation: visualisation de plusieurs histogrammes normalisés d'ensembles de données et ajout d'une courbe de densité KDE à l'histogramme, réglage de différents histogrammes en ut
unity--newtonsoft.json解析