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

一、迪米特法则简介

迪米特法则(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。

五、正反例对比

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

六、总结

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

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

相关推荐
骊山道童7 小时前
设计模式-外观模式
设计模式·外观模式
找了一圈尾巴7 小时前
设计模式(结构型)-享元模式
设计模式·享元模式
骊山道童9 小时前
设计模式-观察者模式
观察者模式·设计模式
自在如风。14 小时前
Java 设计模式:组合模式详解
java·设计模式·组合模式
cccccchd14 小时前
23种设计模式生活化场景,帮助理解
设计模式
未定义.22114 小时前
Java设计模式实战:装饰模式在星巴克咖啡系统中的应用
java·开发语言·设计模式·软件工程
blackA_14 小时前
Java学习——day29(并发控制高级工具与设计模式)
java·学习·设计模式
Antonio91515 小时前
【设计模式】适配器模式
设计模式·oracle·适配器模式
小猪乔治爱打球16 小时前
[Golang修仙之路]单例模式
设计模式