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

news2025/4/16 13:58:47

一、迪米特法则简介

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

五、正反例对比

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

六、总结

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335044.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark-SQL

Spark-SQL 概述 Spark SQL 是 Spark 用于结构化数据(structured data)处理的 Spark 模块 Shark 是伯克利实验室 Spark 生态环境的组件之一,是基于 Hive 所开发的工具,它修改了内存管理、物理计划、执行三个模块,并使之能运行在 Spark 引擎上…

无人机气动-结构耦合技术要点与难点

一、技术要点 1. 多学科耦合建模 气动载荷与结构响应的双向耦合:气动力(如升力、阻力、力矩)导致结构变形,而变形改变气动外形,进一步影响气流分布,形成闭环反馈。 建模方法: 高精度C…

element-ui plus 中 filter-method 函数多次触发问题解决

前情提要 点进这个文章的小伙伴,应该都是为了解决一个需求,把原本的前端过滤改为后端过滤,但是将filter-method修改为后端取数据后,发现其触发了很多次。博主也是在修改表格过滤时用到了这个坑,本篇文章为大家解决一下…

基于【Lang Chain】构建智能问答系统的实战指南

🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是Lang Chain 2、LangChain在问答系统中的核心优…

TestHubo安装及入门指南

TestHubo是一款开源免费的测试管理工具,提供一站式测试解决方案,涵盖功能测试、接口测试、性能测试以及 Web 和 App 测试等多个维度。TestHubo 整合了全面的测试能力,使团队可以在一个平台内完成所有测试需求。本文将介绍如何快速安装配置及入…

react tailwindcss最简单的开始

参考教程: Install Tailwind CSS with Vite - TailwindCSS中文文档 | TailwindCSS中文网https://www.tailwindcss.cn/docs/guides/vite操作过程: Microsoft Windows [版本 10.0.26100.3476] (c) Microsoft Corporation。保留所有权利。D:\gitee\tailwi…

openGauss新特性 | 自动参数化执行计划缓存

目录 自动化参数执行计划缓存简介 SQL参数化及约束条件 一般常量参数化示例 总结 自动化参数执行计划缓存简介 执行计划缓存用于减少执行计划的生成次数。openGauss数据库会缓存之前生成的执行计划,以便在下次执行该SQL时直接使用,可…

3、组件:魔法傀儡的诞生——React 19 组件化开发全解析

一、开篇:魔法傀儡的觉醒 "每个React组件都像一具魔法傀儡,"邓布利多校长挥动魔杖,空中浮现出闪烁的代码字符,"它们能自主思考、协同工作,甚至能跨越时空(服务器与客户端)执行任…

达梦数据库迁移问题总结

更多技术博客,请关注微信公众号:运维之美 问题一、DTS工具运行乱码 开启图形化 [rootlocalhost ~]# xhost #如果命令不存在执行sudo yum install xorg-x11-server-utils xhost: unable to open display "" [rootlocalhost ~]# su - dmd…

OpenHarmony荷兰研习会回顾 | 仓颉语言赋能原生应用开发实践

近日,由全球顶级学术峰会EuroSys/ASPLOS和OpenHarmony社区在荷兰鹿特丹合办的操作系统深度研习会圆满收官,本次研习会以"架构探秘-开发实践-创新实验"三位一体的进阶模式,为全球开发者构建了沉浸式技术探索平台。其中,由…

RV1126 人脸识别门禁系统解决方案

1. 方案简介 本方案为类人脸门禁机的产品级解决方案,已为用户构建一个带调度框架的UI应用工程;准备好我司的easyeai-api链接调用;准备好UI的开发环境。具备低模块耦合度的特点。其目的在于方便用户快速拓展自定义的业务功能模块,以及快速更换UI皮肤。 2. 快速上手 2.1 开…

matlab内置的git软件版本管理功能

1、matlab多人协作开发比普通的嵌入式软件开发困难很多 用过matlab的人都知道,版本管理对于matlab来说真的很费劲,今天介绍的这个工具也不是说它就解决了这个痛点,只是让它变得简单一点。版本管理肯定是不可或缺的,干就完了 2、操作说明 如图所示,源代码管理,选项罗列的…

《前端面试题之 CSS篇(第一集)》

目录 1、CSS的盒模型2、CSS选择器及其优先级3、隐藏元素的方法有那些4、px、em、rem的区别及使用场景5、重排、重绘有什么区别6、水平垂直居中的实现7、CSS中可继承与不可继承属性有哪些8、Sass、Less 是什么?为什么要使用他们?9、CSS预处理器/后处理器是…

MySQL部分总结

mysql学习笔记,如有不足还请指出,谢谢。 外连接,内连接,全连接 外连接:左外、右外 内连接:自己和自己连接 全连接:左外连接右外链接 mysql unique字段 unique可以在数据库层面避免插入相同…

Linux Kernel 2

地址空间(Address Space) 一、物理地址空间(Physical Address Space) 物理地址空间 是指 RAM 和设备内存 在系统内存总线上所呈现的地址布局。 举例:在典型的 32 32 32 位 Intel 架构中, RAM&#xff08…

AndroidTV D贝桌面-v3.2.5-[支持文件传输]

AndroidTV D贝桌面 链接:https://pan.xunlei.com/s/VONXSBtgn8S_BsZxzjH_mHlAA1?pwdzet2# AndroidTV D贝桌面-v3.2.5[支持文件传输] 第一次使用的话,壁纸默认去掉的,不需要按遥控器上键,自己更换壁纸即可

线性方程组的解法

文章目录 线性方程组的解法认识一些基本的矩阵函数MATLAB 实现机电工程学院教学函数构造1.高斯消元法2.列主元消去法3. L U LU LU分解法 线性方程组的解法 看到以下线性方程组的一般形式:设有以下的 n n n阶线性方程组: A x b \mathbf{Ax}\mathbf{b} A…

Python赋能量子计算:算法创新与应用拓展

量子计算与Python结合的算法开发与应用研究 摘要 量子计算作为计算机科学的前沿技术,凭借其独特的计算能力在解决复杂问题方面展现出巨大潜力。Python作为一种高效、灵活的编程语言,为量子计算算法的开发提供了强大的支持。本文从研究学者的视角,系统探讨了量子计算与Pytho…

Java学习笔记(多线程):ReentrantLock 源码分析

本文是自己的学习笔记,主要参考资料如下 JavaSE文档 1、AQS 概述1.1、锁的原理1.2、任务队列1.2.1、结点的状态变化 1.3、加锁和解锁的简单流程 2、ReentrantLock2.1、加锁源码分析2.1.1、tryAcquire()的具体实现2.1.2、acquirQueued()的具体实现2.1.3、tryLock的具…

【软考系统架构设计师】系统配置与性能评价知识点

1、 常见的性能指标 主频外频*倍频 主频1/CPU时钟周期 CPI(Clock Per Instruction)平均每条指令的平均时间周期数 IPC(Instruction Per Clock)每时钟周期运行指令数 MIPS百万条指令每秒 MFLOPS百万个浮点操作每秒 字长影响运算的…