一、迪米特法则简介
迪米特法则(Law of Demeter,简称 LoD),也称为“最少知识法则”,核心思想是:一个对象应当对其他对象有最少的了解,仅与直接相关的对象交互。通过减少对象之间的耦合度,避免直接操作对象的内部结构,可以提高系统的灵活性和可维护性。
二、迪米特法则的核心原则
1.只与直接朋友交互:一个对象应只和直接依赖的对象交互,而避免操作其他对象的内部属性或方法。
2.避免链式调用:链式调用会加深对象间的依赖关系,增加系统复杂度和耦合度。
3.最小化接口暴露:隐藏实现细节,只对外提供必要的功能接口。
三、反例:违反迪米特法则的设计
场景:发动机 ,车 和 司机 3个类间的调用关系。
在反例中,Driver类直接依赖了Car和Engine,破坏了迪米特法则的核心思想。
1.Engine 类
public class Engine {
private String model;
// 构造器,初始化发动机模型
public Engine(String model) {
this.model = model;
}
// 获取发动机模型
public String getModel() {
return model;
}
}
2.Car 类
此类暴露了Enginer 类。
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public Engine getEngine() {
return engine; // 直接暴露 Engine 对象
}
}
3.Driver 类
此类直接访问了Engine 类和 Car类。
public class Driver {
private Car car;
public Driver(Car car) {
this.car = car;
}
public void drive() {
// Driver 直接访问 Engine
Engine engine = car.getEngine();
System.out.println("Driving a car with engine: " + engine.getModel());
}
}
4.Main 类(测试代码)
public class Main {
public static void main(String[] args) {
Engine engine = new Engine("V8");
Car car = new Car(engine);
Driver driver = new Driver(car);
driver.drive(); // 输出: Driving a car with engine: V8
}
}
问题分析
1.违反迪米特法则
• Driver类直接操作了Engine,依赖了Car的内部实现细节。
• 如果Car类的实现发生变化(如更换发动机),Driver类也需要随之修改。
2.高耦合
• Driver同时依赖了Car和Engine,可维护性和扩展性降低。
3.职责分散
• Driver类承担了过多的职责,本应由Car提供的行为被Driver部分替代,导致职责不明确。
四、正例:符合迪米特法则的设计
在正例中,Driver类只与Car类交互,不直接访问Engine的内部实现。
1.Engine 类
(与反例相同,省略重复代码)
2.Car 类
与反例的差别是Car类不暴露Engine类。
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
// 隐藏内部实现细节,提供外部接口
public void startCar() {
System.out.println("Starting car with engine: " + engine.getModel());
}
}
3.Driver 类
与反例的差异是 Driver类只与Car 交互。
public class Driver {
private Car car;
public Driver(Car car) {
this.car = car;
}
public void drive() {
// 只与 Car 类交互,避免直接访问 Engine
car.startCar();
}
}
4.Main 类(测试代码)
public class Main {
public static void main(String[] args) {
Engine engine = new Engine("V8");
Car car = new Car(engine);
Driver driver = new Driver(car);
driver.drive(); // 输出: Starting car with engine: V8
}
}
说明:
• Engine类:负责管理发动机的属性(如模型)。
• Car类:负责管理汽车及其相关操作(如启动汽车)。
• Driver类:负责模拟司机与汽车的互动。
• Main类:测试和展示程序的执行过程。
优化分析
1.遵循迪米特法则:
• Driver类只与Car交互,而不直接访问Engine的内部实现。
• 如果Car类内部实现发生变化(如更换发动机类型),Driver类无需修改。
2.低耦合:
• Driver和Engine之间没有直接依赖,代码更易维护。
3.职责单一:
• Car负责与Engine的交互,Driver只负责操作Car。
4.扩展性高:
• 如果需要为Car增加新功能(如油耗管理),只需修改Car类,无需更改Driver。
五、正反例对比
通过清晰的职责划分和依赖关系解耦,正例设计严格遵循迪米特法则,避免了不必要的实现细节暴露,显著降低了系统的耦合度,提升了代码的可维护性和扩展性。
六、总结
迪米特法则通过限制类与类之间的直接依赖,使系统设计更加松耦合,显著提升代码的可维护性和扩展性。遵循这一法则,开发者可以减少因需求变更而引发的代码改动范围,从而保持系统的稳定性和灵活性。
在设计时,应优先隐藏实现细节,确保类之间职责单一、依赖清晰,以构建灵活易维护的高质量系统。