迪米特法则也叫做“最少知识”原则。

定义

一个对象应该对其他对象保持最少的了解。

在《Head First 设计模式》一书中,针对该原则也强调:只和你的密友交流。

这里提到的密友指的是:

  • 当前对象本身
  • 当前对象的成员对象
  • 当前对象所创建或者实例化的对象
  • 当前对象的的方法参数

这些个对象和当前对象之间存在关联、聚合或者组合关系,可以直接访问这些对象的方法。

示例

/**
 * @author zhh
 * @description 汽车类
 * @date 2019-08-13 23:44
 */
public class Car {

    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start(Key key) {
        Doors doors = new Doors();
        doors.lock();

        boolean turns = key.turns();

        if (turns) {
            engine.start();
            updateDashboard();
        }
    }

    /**
     * 更新面板
     */
    public void updateDashboard() {
        System.out.println("更新面板");
    }
}
/**
 * @author zhh
 * @description 车门类
 * @date 2019-08-13 23:49
 */
public class Doors {
    /**
     * 关上车门
     */
    public void lock() {
        System.out.println("关上车门");
    }
}
/**
 * @author zhh
 * @description 引擎类
 * @date 2019-08-13 23:45
 */
public class Engine {
    /**
     * 启动引擎
     */
    public void start() {
        System.out.println("启动引擎");
    }
}
/**
 * @author zhh
 * @description 钥匙类
 * @date 2019-08-13 23:46
 */
public class Key {
    /**
     * 转动钥匙
     */
    public boolean turns() {
        System.out.println("转动钥匙");
        return true;
    }
}

在上述代码中,我们主要看最前面的汽车类

  • Engine 对象作为当前 Car 对象的成员变量,我们能够直接调用它的方法
  • Key 对象作为 Car 对象 start() 方法的入参,它的方法也能够直接被调用
  • Doors 对象是 Car 对象 start() 方法实例化的对象,它的方法也可以被调用
  • updateDashboard() 是 Car 对象本身的方法,可以直接调用

综上,该汽车类遵循了最少知识原则。

优点

  • 降低类之间的耦合,提高模块的相对独立性。
  • 提高类的可复用性和系统的扩展性。

缺点

过度使用迪米特法则会使系统产生大量中介类,从而增加系统的复杂性,使模块之间的通信效率降低。

总结

迪米特法则主要强调以下两点:

  • 从依赖者的角度来说,只依赖应该依赖的对象。
  • 从被依赖者的角度说,只暴露应该暴露的方法。

注意点

  • 类的划分上,应创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。
  • 在类的结构设计上,尽量降低类成员的访问权限。
  • 在类的设计上,优先考虑将一个类设置成不变类。
  • 在对其他类的引用上,将引用其他对象的次数降到最低。
  • 不暴露类的属性成员,而应该提供相应的 get 和 set 方法。
  • 谨慎使用序列化 (Serializable) 功能。