迪米特法则是七个面向对象设计原则中相对比较容易理解的一个法则,他要求了软件实体类设计之间的松耦合。接下来老四就稍微浅析一下这个法则,希望帮助你加深一下印象,关于面向对象设计原则有哪七个?如下(不出意外的话会壹壹浅析):
- 单一职责原则,老四已经浅析,请戳《浅析设计模式第三章之单一职责原则》
- 开放-封闭原则,老四已经浅析,请戳《浅析设计模式第四章之开放-封闭原则》
- 里氏代换原则,老四已经浅析,具体内容包含在下面的关于依赖倒转原则当中,请戳下一条链接
- 依赖倒转原则,老四已经浅析,请戳《浅析设计模式第五章之依赖倒转原则》,里面包含里氏代换原则的浅析
- 接口隔离原则
- 合成复用原则
- 迪米特法则
定义
迪米特法则(Law of Demeter,LoD): 如果两个类不比彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。换句话说就是: 一个软件实体应当尽可能少地与其他实体发生相互作用。迪米特法则又名也叫最少知识原则(LeastKnowledge Principle, LKP);
迪米特法则强调的前提就是在类的结构设计上,每一个类都应当尽量降低成员访问权限。根本思想其实就是降低实体类之间的松耦合。我们都知道,类之间的耦合性越弱,越有利于复用,拓展就会相对容易,一个单独的类及时被修改也不会对其他的类造成影响。这就要求我们在软件设计当中,尽量减少对象之间的交互,及时要交互,要像定义所述的那样,找一个第三者转发调用。
可能在技术讲解中,文字稍微显得苍白一些,接下来老四附上几个类的代码再来理解一下迪米特法则。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.glorze.common; /** * 文本标签类 * @ClassName Label * @author: glorze.com * @since: 2018年6月30日 下午11:53:54 */ public class Label { public void showLabel() { System.out.println("显示文本标签"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.glorze.common; /** * 列表框类 * @ClassName List * @author: glorze.com * @since: 2018年6月30日 下午11:55:22 */ public class List { public void showList() { System.out.println("显示列表框"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.glorze.common; /** * 按钮类 * @ClassName Button * @author: glorze.com * @since: 2018年7月1日 上午12:11:00 */ public class Button { public void clickButton(Label label) { System.out.println("执行按钮点击操作: 显示文本标签"); label.showLabel(); } public void clickButton(List list) { System.out.println("执行按钮点击操作: 显示列表框"); list.showList(); } public static void main(String[] args) { Button button = new Button(); Label label = new Label(); List list = new List(); button.clickButton(label); System.out.println("================"); button.clickButton(list); } } |
输出结果:
执行按钮点击操作: 显示文本标签
显示文本标签
================
执行按钮点击操作: 显示列表框
显示列表框
以上代码我们看到,老四写的这个控件业务设计,按钮与文本标签、列表框控件存在相对纠结复杂的交互关系,按钮的点击事件可能需要触发另外两个类的操作,反过来Label与List类相互之间也可能会有交互操作,这样的设计导致我们如果新加一个控件的话到时候就可能既需要修改Label类,又要修改List类,甚至修改Button中的方法。
接下来我们遵守迪米特法则,让按钮们各司其职,如果需要调用其他的类的方法均通过Transfer类来完成,Transfer作为一个中转类来为各个组件的交互提供强有力的支持。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.glorze.demeter; import com.glorze.common.Label; import com.glorze.common.List; /** * 组件中转类 * @ClassName Transfer * @author: glorze.com * @since: 2018年7月1日 上午12:03:36 */ public class Transfer { private Label label = new Label(); private List list = new List(); public void showLabel() { label.showLabel(); } public void showList() { list.showList(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.glorze.demeter; /** * 遵守迪米特法则的按钮类 * @ClassName Button * @author: glorze.com * @since: 2018年7月1日 上午12:18:39 */ public class Button { public void clickButton(Transfer transfer) { System.out.println("执行按钮点击操作: 显示文本标签"); transfer.showLabel(); } public void excuteButton(Transfer transfer) { System.out.println("执行按钮点击操作: 显示列表框"); transfer.showList(); } public static void main(String[] args) { Button button = new Button(); Transfer transfer= new Transfer(); button.clickButton(transfer); System.out.println("====我是丑逼分割线===="); button.excuteButton(transfer); } } |
输出结果:
执行按钮点击操作: 显示文本标签
显示文本标签
====我是丑逼分割线====
执行按钮点击操作: 显示列表框
显示列表框
我们通过Transfer中转类降低了各个组件之间的耦合性,界面空间之间不在发生直接饮用,而是将请求先转发给中转类,再由中转类来完成对其他组件的调用,对于增删改的组件我们只需要修改Transfer中转类即可。
更博不易,喜欢的老铁有能力烦请赞助盒烟钱,点我去赞助。抱拳。