设计原则--迪米特法则(LoD)
什么是迪米特法则:
迪米特法则包含四层含义:
(1)只和朋友交流:
//老师类 public class Teacher { //老师对学生发布命令, 清一下女生 public void commond(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()); } } //女生类:没有任何的代码 public class Girl { } //我们使用Client来描绘一下这个场景 public class Client { public static void main(String[] args) { Teacher teacher= new Teacher(); //老师发布命令 teacher.commond(new GroupLeader()); } }
首先来看 Teacher 有几个朋友,就一个 GroupLeader 类,这个 就是朋友类,朋友类是怎么定义的呢? 出现在成员变量、方法的输入输出参数中的类被称为成员朋友类, 迪米特法则说是一个类只和朋友类交流, 但是 commond 方法中我们与 Girl 类有了交流,声明了一个 List动态数组,也就是与一个陌生的类 Girl 有了交流,这个不好,那我们再来修改一下,类图还是不变,先修改一下 GroupLeader 类:
//老师类 public class Teacher { //老师对学生发布命令, 清一下女生 public void commond(GroupLeader groupLeader){ //告诉体育委员开始执行清查任务 groupLeader.countGirls(); } } //体育委员类 public class GroupLeader { //有清查女生的工作 public void countGirls(){ List<Girl> listGirls = new ArrayList<Girl>(); //初始化女生 for(int i=0;i<20;i++){ listGirls.add(new Girl()); } System. out.println(" 女生数量是: "+listGirls.size()); } }
程序做了一个简单的修改,就是把 Teacher 中的对 List初始化
移动到了 GroupLeader 的 countGrils 方法中,避开了 Teacher 类对陌生类 Girl 的访问, 减少系统间的耦合
(2)朋友之间也有距离:
人和人之间是有距离的,太远就不是朋友了,太近就浑身不自在,这和类间 系也是一样,即使朋友类也不能无话不说,无所不知。
在项目中应该都碰到过这样的需求:调用一个 类,然后必须是先执行第一个方法,然后是第二个方法,根据返回结果再来看是否可以调用第三个方法, 或者第四个方法等等。
实现软件安装过程的第一步做什么、第二步做什么、第三步做什么这样一个过程,我 们来看三个类的源代码,先看 Wizard 的源代码:
//按照步骤执行的业务逻辑类 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); } } //业务组装类,负责调用各个步骤 public class InstallSoftware { public void installWizard(Wizard wizard){ int first = wizard.first(); //根据first返回的结果,看是否需要执行second if(first>50){ int second = wizard.second(); if(second>50){ int third = wizard.third(); if(third >50){ wizard.first(); } } } } } //业务场景调用 public class Client { public static void main(String[] args) { InstallSoftware invoker = new InstallSoftware(); invoker.installWizard(new Wizard()); } }
运行结果和随机数有关,我们想想这个程序有什么问题吗? Wizard 类把太多的方法暴露给 InstallSoftware 类了,这样耦合关系就非常紧了,我想修改一个方法的返回值,本来是 int 的,现在修改为 boolean,你看就需要修改其他的类,这样的耦合是极度不合适的, 迪米 特法则就要求类“小气”一点,尽量不要对外公布太多的 public 方法和非静态的 public 变量, 尽量内敛。
//按照步骤执行的业务逻辑类 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 = this.first(); //根据first返回的结果,看是否需要执行second if(first>50){ int second = this.second(); if(second>50){ int third = this.third(); if(third >50){ this.first(); } } } } }
//业务组装类,负责调用各个步骤 public class InstallSoftware { public void installWizard(Wizard wizard){ //不废话,直接调用 wizard.installWizard(); } }
Client 类没有任何改变,就不在拷贝了,这样我们的程序就做到了弱耦合,需要做的是:减少 public 方法,多使用 private、
protected 等访问权限,减少非 static 的 public 属性,如果成员变量 或方法能加上 final 关键字就加上,不要让外部去改变它。
(3)是自己的就是自己的:如果一个方法放在本类中,既不增加类之间的关系,也对本类不产生负面影响,那就放在本类中。
(4)谨慎使用Serializable:
这个问题会很少出现的,即使出现也会马上发现问题。 举个例子来说,如果你使用 R M I 的方式传递一个对象 VO( Value Object),这个对象就必须使用 Serializable 接口,也就是把你的这个对象进行序列化,然后进行网络传输。突然有一天,客户端的 VO 对象修改了一个 属性的访问权限,从 private 变更为 public 了,如果服务器上没有做出响应的变更的话,就会报序列化失败。 这个应该属于项目管理范畴,一个类或接口客户端变更了,而服务端没有变更。
文章来源:设计模式之禅

浙公网安备 33010602011771号