面向对象设计的原则---------迪米特原则(转)
迪米特原则(Law of Demeter)
1、迪米特原则的定义
迪米特原则也叫最少知识原则(Least Knowledge Principle, LKP)简单的说,就是如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果一个类需要调用类另一个类的某个方法的话,应当通过第三个类来转发调用。迪米特法则可以简单说成:talk only to your immediate friends。
2、迪米特原则解释
一个软件实体应当尽可能少的与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。迪米特法则减少耦合的问题,类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。也就是说,信息的隐藏促进了软件的复用。
3、迪米特原则含义
(1)、talk only to your immediate friends.只和直接朋友通信。在一个类中,出现在成员变量、方法的输入输出参数中的类被称为成员朋友类。
实例:张三李四是朋友关系,李四王五是朋友关系.张三和王五是陌生人关系,为了保证张三和王五不认识,而张三又能调用王五中的方法,通过一个李四作为中继,把张三和王五隔离开来。
(2)、迪米特法则就要求类“小气”一点,尽量不要对外公布太多的public 方法和非静态的public 变量,尽量内敛,
多使用private,package-private、protected 等访问权限。
实例:在软件的安装中,一个类中定义了多个步骤,同时一个类要调用此类中的方法完成安装,此时可以在客户端的类中随即地调用这些步骤,这样前边的类就定义多个public的方法,我们转换一种思路,把这些步骤方法都设置为private,同时,引入一个总的方法,在总的方法中调用安装步骤方法,避免了客户类和此类中多个方法的接触。
import java.util.Random; /** * 按照步骤执行的业务逻辑类 */ 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(); } }
(3)、如果一个方法放在本类中,即不增加类间关系,也对本类不产生负面影响,就放置在本类中。组合/聚合与之相似。
(4)、谨慎使用Serializable。
4、迪米特原则优缺点
由于狭义迪米特法则要求当两个类不必直接通信时,进行方法调用应当由第三个类来转发调用,这样就会在系统里制造出大量的小方法,是的系统显的凌乱。
迪米特法则的知识最小化,可以使得局部的模块得到简化,但是同时也会造成模块间的通信效率降低,使模块间不容易协调。
迪米特法则讨论的是对象之间信息的流量,方向以及信息影响的控制。其主要意图是控制信息过载,这就要求一个模块一个应当尽可能将自己的内部数据和实现细节隐藏起来,也就是要求有良好的封装。
因此,在类设计上的应用优先考虑将一个类设计成不变类,即使这个类是可变的在给她的属性设置赋值方法时,也应当尽可能的吝啬,除非确实需要,否则不要对该属性增加赋值方法。尽量降低一个类的访问权限,谨慎使用Serializable,尽量降低成员的访问权限。
设计模式的门面模式(Facade)和中介模式(Mediator),都是迪米特法则应用的例子。