设计模式:迪米特法则 - 最少依赖,实现高内聚低耦合

一、迪米特法则简介

迪米特法则(Law of Demeter,简称 LoD),也称为"最少知识法则",核心思想是:一个对象应当对其他对象有最少的了解,仅与直接相关的对象交互。通过减少对象之间的耦合度,避免直接操作对象的内部结构,可以提高系统的灵活性和可维护性。

二、迪米特法则的核心原则

1.只与直接朋友交互:一个对象应只和直接依赖的对象交互,而避免操作其他对象的内部属性或方法。

2.避免链式调用:链式调用会加深对象间的依赖关系,增加系统复杂度和耦合度。

3.最小化接口暴露:隐藏实现细节,只对外提供必要的功能接口。

三、反例:违反迪米特法则的设计

场景:发动机 ,车 和 司机 3个类间的调用关系。

在反例中,Driver类直接依赖了Car和Engine,破坏了迪米特法则的核心思想。

1.Engine 类

java 复制代码
public class Engine {
    private String model;

    // 构造器,初始化发动机模型
    public Engine(String model) {
        this.model = model;
    }

    // 获取发动机模型
    public String getModel() {
        return model;
    }
}

2.Car 类

此类暴露了Enginer 类。

java 复制代码
public class Car {
    private Engine engine;

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

    public Engine getEngine() {
        return engine; // 直接暴露 Engine 对象
    }
}

3.Driver 类

此类直接访问了Engine 类和 Car类。

java 复制代码
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 类(测试代码)

java 复制代码
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类。

java 复制代码
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 交互。

java 复制代码
public class Driver {
    private Car car;

    public Driver(Car car) {
        this.car = car;
    }

    public void drive() {
        // 只与 Car 类交互,避免直接访问 Engine
        car.startCar();
    }
}

4.Main 类(测试代码)

java 复制代码
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。

五、正反例对比

通过清晰的职责划分和依赖关系解耦,正例设计严格遵循迪米特法则,避免了不必要的实现细节暴露,显著降低了系统的耦合度,提升了代码的可维护性和扩展性。

六、总结

迪米特法则通过限制类与类之间的直接依赖,使系统设计更加松耦合,显著提升代码的可维护性和扩展性。遵循这一法则,开发者可以减少因需求变更而引发的代码改动范围,从而保持系统的稳定性和灵活性。

在设计时,应优先隐藏实现细节,确保类之间职责单一、依赖清晰,以构建灵活易维护的高质量系统。

相关推荐
饕餮争锋3 小时前
设计模式笔记_行为型_观察者模式
笔记·观察者模式·设计模式
我命由我123456 小时前
软件开发 - 避免过多的 if-else 语句(使用策略模式、使用映射表、使用枚举、使用函数式编程)
java·开发语言·javascript·设计模式·java-ee·策略模式·js
long3166 小时前
java 策略模式 demo
java·开发语言·后端·spring·设计模式
汤姆大聪明6 小时前
【软件设计模式】前置知识类图、七大原则(精简笔记版)
笔记·设计模式
饕餮争锋10 小时前
设计模式笔记_行为型_策略模式
笔记·设计模式·策略模式
易元10 小时前
模式组合应用-桥接模式(一)
后端·设计模式
是2的10次方啊10 小时前
🕺 行为型设计模式:对象协作的舞蹈家(中)
设计模式
the sun3411 小时前
常见的设计模式(2)单例模式
单例模式·设计模式
是2的10次方啊12 小时前
🕺 行为型设计模式:对象协作的舞蹈家(上)
设计模式
一乐小哥14 小时前
从面试高频到实战落地:单例模式全解析(含 6 种实现 + 避坑指南)
java·设计模式