六大设计原则之迪米特原则
迪米特原则的定义
迪米特原则(Law of Demeter,LoD),也叫最少知识原则(Low knowledge Principle,LKP):
一个对象应该对其他对象有最少的了解。
通俗的讲:一个类对自己需要耦合或调用的类知道的最少,你(被耦合或调用的类)的内部是如何复杂和我没有关系,我就知道你提供的public方法,我只调用这些方法,其它的我不关心。
迪米特原则的具体要求
迪米特原则对类的低耦合提出了明确的要求:
只与朋友类交流
迪米特原则还有一个解释:Only talk to your immediate friends(只与直接朋友通信)。
什么叫直接朋友呢?每个对象都必然会与其他对象有耦合关系,两个对象之间的耦合就成为朋友关系,这种关系类型有很多,例如:组合,聚合,依赖等。朋友类也可以这样定义:出现在成员变量,方法的输入输出参数中的类,称为朋友类。
上体育课,我们经常有这样一个场景:
体育老师上课前要体育委员确认一下全班女生到了多少位,也就是体育委员清点女生的人数。类图如下:
老师类:
public class Teacher{//老师对体育委员发一个命令,让其清点女生人数public void command(GroupLeader groupLeader){List<Girl> listGirls = new ArrayList();//初始化女生for(int i=0;i<20;i++){listGirls.add(new Girl());}//告诉体育委员开始清点女生人数groupLeader.countGirls(listGirls);}
}
体育委员类:
public class GroupLeader{//清点女生数量public void countGirls(List<Girl> listGirls){System.out.println("女生人数是:"+listGirls.size());}
}
女生类:
publci class Girl{
}
场景类:
public class Client{public static void main(Strings[] args){Teacher teacher = new Teacher();//老师给体育委员发清点女生人数的命令teacher.command(new GroupLeader());}}
我们再回头看Teacher类,Teacher类只有一个朋友类GroupLeader,Girl类不是朋友类,但是Teacher与Girl类通信了,这就破坏了Teacher类的健壮性,Teacher类的方法竟然与一个不是自己的朋友类Girl类通信,这是不允许的,严重违反了迪米特原则。
我们对程序进行如下修改,将类图修改如下:
修改后的老师类:
public class Teacher{//老师对体育委员发一个命令,让其清点女生人数public void command(GroupLeader groupLeader){//告诉体育委员开始清点女生人数groupLeader.countGirls();}
}
修改后的体育委员类:
public class GroupLeader{private List<Girl> listGirls;public GroupLeader(List<Girl> listGirls){this.listGirls = listGirls;}//清点女生数量public void countGirls(){System.out.println("女生人数是:"+listGirls.size());}
}
修改后的场景类:
public class Client{public static void main(Strings[] args){//产生女生群体List<Girl> listGirls = new ArrayList<Girl>();//初始化女生for(int i=0;i<20;i++){listGirls.add(new Girl());}Teacher teacher = new Teacher();//老师给体育委员发清点女生人数的命令teacher.command(new GroupLeader(listGirls));}
}
对程序修改,把Teacher中对Girl群体的初始化移动到场景类中,同时在GroupLeader中增加对Girl的注入,避开了Teacher类对陌生类Girl的访问,降低了系统间的耦合,提高了系统的健壮性。
朋友类间也是要有距离
我们在安装软件时,经常会有一个安装向导的过程。比如第一步确认是否安装,第二步确认License,第三步选择安装目录…。这个是一个典型的顺序执行动作,我们定义软件安装过程的类图如下:
导向类:
public class Wizard{private Random rand = new Random(System.currentTimeMillis());//第一步public int first(){System.out.println("执行第一个方法.....");return rand.nextInt(100);}//第二步public int second(){System.out.println("执行第二个方法.....");return rand.nextInt(100);}//第三步public int third(){System.out.println("执行第三个方法.....");return rand.nextInt(100);}
}
InstallSoftware类:
public class InstallSoftware{public void installWizard(Wizard wizard){int first = wizard.first();//根据first返回的结果,看是否要执行下一步if(first >50){int second = wizard.second();if(second >50){wizard.third();}} }}
场景类:
public class Client{public static void main(Strings[] args){InstallSoftware invoker = new InstallSoftware();invoker.installWizard(new Wizard());}
}
以上的程序非常简单,但是隐藏了一个问题。Wizard类把太多的方法暴露给InstallSoftware类,导致两者的关系太亲密,耦合关系变量异常牢固。我们把Wizard类进行重构,uml类图如下:
修改后的Wizard类:
public class Wizard{private Random rand = new Random(System.currentTimeMillis());//第一步private int first(){System.out.println("执行第一个方法.....");return rand.nextInt(100);}//第二步private int second(){System.out.println("执行第二个方法.....");return rand.nextInt(100);}//第三步private int third(){System.out.println("执行第三个方法.....");return rand.nextInt(100);}//软件安装过程public void installWizard(){int first = wizard.first();//根据first返回的结果,看是否要执行下一步if(first >50){int second = wizard.second();if(second >50){wizard.third();}} }
}
修改后的InstallSoftware类:
public class InstallSoftware{public void installWizard(Wizard wizard){wizard.installWizard()}
}
通过重构,类间的耦合关系变弱了,结构变得清晰,变量的风险也变小了。
一个类公开的public方法和属性越多,修改时涉及的面也就越大,变更引起的风险扩散也就越大。因此,为了保持朋友类间的距离,在设计时需要反复衡量:是否还可以再减少public方法和属性,是否可以修改为private,package-private,protected等访问权限,是否可以加上final关键字。
注意:
迪米特原则要求类“羞涩”一点,尽量不要对外公开太多的public方法和非静态的public变量,尽量内敛,多使用private,package-private,protected等访问权限。
##是自己的就是自己的
在实践中经常出现这样一个方法,放在本类中也可以,放到其它类中也可以。那怎么处理呢?你可以坚持一个原则:如果一个方法放在本类中,即不增加类间关系,也对本类不产生负面影响,那就放到本类中。
迪米特原则的实践
迪米特原则的核心观念就是类间解耦,弱耦合,只有弱耦合后,类的复用率才可以提高。其结果就是产生了大量的中转或跳转类,导致系统复杂,为维护带来了难度。所以,我们在实践时要反复权衡,即要让结构清晰,又做到高内聚低耦合。
参考:
设计模式之禅 秦小波著 机械工业出版社
六大设计原则之迪米特原则相关推荐
- 设计原则之迪米特原则
迪米特原则 Law of Demeter, LOD 迪米特原则定义 迪米特原则也叫最小知识原则(The Least Knowledge Principle).即,每个模块只应该了解那些与它关系密切的模 ...
- 软件设计原则之接口隔离原则、合成复用原则、迪米特原则
系列文章目录 软件设计原则之单一职责原则.开闭原则 软件设计原则之里氏替换原则.依赖倒置原则 软件设计原则之接口隔离原则.合成复用原则.迪米特原则 文章目录 系列文章目录 一.接口隔离原则 什么是接口 ...
- 【学习笔记】慕课网—Java设计模式精讲 第3章 软件设计七大原则-3-6 迪米特原则(最少知道原则)...
/** * 软件设计七大原则-迪米特原则 学习笔记 * @author cnRicky * @date 2018.11.10 */ 迪米特原则(最少知道原则) 一个对象应该对其他对象保持最少的了解.又 ...
- C# 设计原则 之 迪米特 原则
迪米特法则又叫作最少知道原则,一般设计用于 对类内部 进行 合适的封装. 下面举例: 人关闭电脑的 示例 1.1没有实现 迪米特原则的 代码 namespace 迪米特 {internal class ...
- 设计模式:六大原则之迪米特原则
迪米特原则 基本介绍 定义:迪米特法则也称为最少知识原则,即一个对象应该对其他对象有最少的了解.通俗地说,一个类应该对自己需要耦合或调用的类知道的最少,被调用或耦合的类的内部是如何复杂都和我没有关系. ...
- 面向对象的六大原则之 —— 迪米特原则
学习了何红辉.关爱民写的<Android设计模式>,对于面向对象的六大原则有进一步的理解,特此根据自己的理解记录总结一下 什么是迪米特原则 也称为最少知识原则,意思就是一个对象应该对其他对 ...
- 设计模式-设计原则之迪米特原则
例子 假设老板给项目组长下达一个任务,让其去查询课程的数量 代码 public class Course {} public class TeamLeader {public void checkNu ...
- 程序设计原则之迪米特原则
一.什么是迪米特原则 迪米特原则也叫最小知道原则,即对其他的类尽量保持最少知道.只关心自己的直接朋友类,而不关心其他的类. 直接朋友类:出现在自己的域中.方法入参中.方法出参中的类叫直接朋友类:那些在 ...
- 设计模式(6)之七大原则之迪米特原则
一.定义 迪米特法则(Law of Demeter,LoD)又叫作最少知识原则(Least Knowledge Principle,LKP),产生于 1987 年美国东北大学(Northeastern ...
最新文章
- 高文院士:为什么中国的AI发展必须要有开源开放平台?
- EHPC通过断点续算和自动伸缩在抢占式实例上实现低成本HPC计算
- mysql开启慢查询
- java记录log信息
- 老男孩Day1作业(一):编写登录接口
- java类变量什么时候初始化_Java类变量的初始化时机
- linux程序库设置错误,Citrix在Arch Linux中无效 – 库错误
- 基于SSM的家庭理财系统
- C# ASP.NET里@的妙用
- OpenCV 禁止吸烟图像拼接
- TLS Lab(Transport Layer Security Lab,SEED实验)基于PKI实验内容进行中间人攻击实验
- 非共识大会 | 伍鸣博士:DApp发展需要一条高性能且安全的公链
- 德国留学语言c1,德国留学 纯语言签证和语言加留学签的区别介绍
- ARM中的MOV指令
- am335x uboot启动流程分析
- STM32串口中断接收标记USART_RX_STA 学习
- Log4C的基本用法
- CSDN湖大高校俱乐部活动的吐槽
- 解读STEAM教育中的表现性评价
- 曾想亲手解析未知化合物晶体结构
热门文章
- Win10:系统重装、优化、必备软件——备忘笔记
- 重庆计算机应用学校,重庆财政学校-计算机应用
- 微信小程序--顶部轮播图
- OSChina 周六乱弹 —— 我读书少你别骗我!【多图】
- 【mean teacher】IndexError: invalid index of a 0-dim tensor. Use `tensor.item()` in Python o的解决
- 短视频为什么要坚持原创?如何创作原创短视频内容
- T31快启图像效果优化
- 1 盒用 1 年,这个防雾黑科技,让你的眼镜再也不起雾!
- Levenshtein distance:算法整理 与 编辑操作推断 【回朔 + Python】
- 过路费jzyzoj 1218 (Floyd)