迪米特法则(Demeter)
定义
一个软件实体尽量少的与其他实体发生相互作用。
原则
不要和“陌生人”说话、只与你的直接朋友通信。
其中直接朋友包含以下几类:
(1) 当前对象本身(this);
(2) 以参数形式传入到当前对象方法中的对象;
(3) 当前对象的成员对象;
(4) 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;
(5) 当前对象所创建的对象。
应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。
例子
在体育场上,老师命令队长把全队的女生人数数出来。
女生类
package com.csdhsm.pattemdesign.demeter; /** * @Title: Girl.java * @Description: 女生类 * @author: Han * @date: 2016年6月22日 下午7:55:48 */ public class Girl { }
队长类
package com.csdhsm.pattemdesign.demeter; import java.util.List; /** * @Title: GroupLeader.java * @Description: 队长类 * @author: Han * @date: 2016年6月22日 下午7:52:42 */ public class GroupLeader { //数女生个数 public void countGirls(List<Girl> listGirls) { System.out.println(listGirls.size()); } }
教师类package com.csdhsm.pattemdesign.demeterimport java.util.ArrayList;
import java.util.List; /** * @Title: Teacher.java * @Description: 教师类 * @author: Han * @date: 2016年6月22日 下午7:54:37 */ public class Teacher { //命令队长数女生的个数 public void commond(GroupLeader leader) {
List<Girl> listGirls = new ArrayList<>(); for(int i = 0; i < 20; i++) { listGirls.add(new Girl()); } leader.countGirls(listGirls); } }
客户端
package com.csdhsm.pattemdesign.demeter; public class Solution { public static void main(String[] args) { Teacher teacher = new Teacher(); GroupLeader leader = new GroupLeader(); teacher.commond(leader); } }
问题
看起来没有什么问题,但是在教师应该是给队长下命令,队长和女生耦合,List<Girl> listGirls = new ArrayList<>();,直接与不是“朋友”的Girl相互关联,使得整个系统耦合度高,不易维护和扩展。
修改之后
女生类和客户端类不变。
队长类
package com.csdhsm.pattemdesign.demeter; import java.util.ArrayList; import java.util.List; /** * @Title: GroupLeader.java * @Description: 队长类 * @author: Han * @date: 2016年6月22日 下午7:52:42 */ public class GroupLeader { List<Girl> listGirls = new ArrayList<>(); //数女生个数 public void countGirls() { for(int i = 0; i < 20; i++) { listGirls.add(new Girl()); } System.out.println(listGirls.size()); } }
教师类
package com.csdhsm.pattemdesign.demeter; /** * @Title: Teacher.java * @Description: 教师类 * @author: Han * @date: 2016年6月22日 下午7:54:37 */ public class Teacher { //命令队长数女生的个数 public void commond(GroupLeader leader) { leader.countGirls(); } }
这样耦合度就大大降低了。
总结
迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,例如本例中,总公司就是通过队长这个“中介”来与女生联系的。过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合。