设计原则之--迪米特法则

来源:互联网 发布:word加密软件 编辑:程序博客网 时间:2024/05/21 05:23
迪米特法则,又叫做最少知识原则(Least Knowledge Principle):如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

迪米特法则,其根本思想,是强调了类之间的松耦合。

迪米特法则,另外几种表述方式:
只与你直接的朋友们通信(only talk to your immediate friends)
不要与“陌生人”说话(do not talk to strangers)
每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

以下的条件成为“朋友”条件:
当前对象本身(this)
以参量形式传入到当前对象中的方法
当前对象的实例变量直接引用的对象
当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友
当前对象所创建的对象
如果满足上面条件之一,就是当前对象的“朋友”,负责就是“陌生人”

下面从代码重构的角度讨论怎样将一个不符合迪米特法则的系统,重构成为复合迪米特法则的系统。
系统中有3个类,Someone,Friend,Stranger,其中Someone与Friend是朋友,Friend与Stranger是朋友,系统结构图如下:其中Friend持有Stranger的引用,所以是朋友,在代码中可以看到Someone接受Friend作为参量,因此二者是朋友。

public class ASomeone {public void operation1(AFriend friend){System.out.println("通过Someone来调用Stranger");AStranger stranger = friend.provide();stranger.operation3();}public static void main(String[] args) {new ASomeone().operation1(new AFriend());}}public class AFriend {private AStranger stranger = new AStranger();public AStranger provide(){return stranger;}public void operation2(){}}public class AStranger {public void operation3(){System.out.println("调用了陌生人的函数");}}
运行结果:
通过Someone来调用Stranger调用了陌生人的函数

显然Someone的方法operation1方法不满足迪米特法则,因为这个方法引用了Stranger对象,而Stranger对象不是Someone的朋友。

改造之后的结构图:

与改造前相比,Someone与Stranger之间的联系已经没有了,Someone不需要知道Stranger的存在就可以做同样的事情。代码如下:
public class CSomeone {public void operation1(CFriend cfriend){cfriend.forward();}public static void main(String[] args) {new CSomeone().operation1(new CFriend());}}public class CFriend {private CStranger cstranger = new CStranger();public void operation2(){}public void forward(){System.out.println("通过Friend来调用Stranger");cstranger.operation3();}}public class CStranger {public void operation3(){System.out.println("调用了陌生人的函数");}}
运行结果:
通过Friend来调用Stranger调用了陌生人的函数

由于原来Friend类的forward方法所做的事情就是以前Someone要做的事情,使用了Stranger的operation3方法,而这种forward方法叫做转发方法。
由于使用了调用转发,使得调用的细节被隐藏在Friend内部,从而使得Someone与Stranger之间的直接联系被省略掉了。这样一来,使得系统内部的耦合度降低,在系统的某个类需要被修改时,仅仅会直接影响到这个类的“朋友”们,不会直接影响其余部分。

与依赖反转法则相辅助,引进一个抽象的AbstractStranger角色,让Someone依赖于这个角色,从而是Someone与Stranger的具体实现脱耦。如下图:

public abstract class AbstractStranger {public void operation3(){};}public class ASomeone {public void operation1(AFriend friend){System.out.println("通过Someone来调用Stranger");AStranger stranger = friend.provide();stranger.operation3();}public static void main(String[] args) {new ASomeone().operation1(new AFriend());}}public class AFriend {private AStranger stranger = new AStranger();public AStranger provide(){return stranger;}public void operation2(){}}public class AStranger {public void operation3(){System.out.println("调用了陌生人的函数");}}
运行结果:
通过Someone来调用Stranger调用了陌生人的函数





原创粉丝点击