【6大设计原则】迪米特法则:解密软件设计中的“最少知识原则”

在这里插入图片描述

引言

在软件设计中,设计原则是指导我们构建高质量、可维护系统的基石。迪米特法则(Law of Demeter,LoD),也被称为“最少知识原则”,是六大设计原则之一。它强调对象之间的松耦合,确保系统的各个部分之间的依赖关系尽可能少,从而提高系统的灵活性和可维护性。本文将深入探讨迪米特法则的核心思想、应用场景以及如何在实际开发中有效运用这一原则。

迪米特法则的核心思想

迪米特法则的核心思想可以用一句话概括:一个对象应当对其他对象有尽可能少的了解。具体来说,一个对象应当只与其直接的朋友通信,而不应当与朋友的朋友通信。这里的“朋友”通常指的是对象的成员变量、方法参数或返回值。

迪米特法则的定义

在这里插入图片描述

迪米特法则可以进一步细化为以下几点:

  1. 只与直接的朋友通信:一个对象的方法只能调用以下几种对象的方法:

    • 该对象本身
    • 作为方法参数传入的对象
    • 该对象的成员变量
    • 该方法创建的局部对象
  2. 避免与“陌生人”通信:一个对象不应调用由另一个对象的方法返回的对象的方法。

迪米特法则的优点

  • 降低耦合度:通过限制对象之间的通信,迪米特法则减少了对象之间的依赖关系,使得系统更容易维护和扩展。
  • 提高模块化:遵循迪米特法则可以使系统中的各个模块更加独立,从而提高系统的模块化程度。
  • 增强可测试性:松耦合的系统更容易进行单元测试,因为每个模块都可以独立测试。

迪米特法则的应用场景

场景一:避免链式调用

链式调用是指通过多个对象的方法调用链来完成一个操作。例如:

customer.getOrder().getOrderItem().getProduct().getName();

在这个例子中,customer对象通过链式调用获取product的名称。这种调用方式违反了迪米特法则,因为它要求customer对象了解orderorderItemproduct的内部结构。

改进方案

可以通过在customer对象中添加一个方法来封装链式调用:

public String getProductName() {
    return this.order.getOrderItem().getProduct().getName();
}

这样,customer对象只需要了解order对象,而不需要了解orderItemproduct的内部结构。

场景二:封装内部细节

假设有一个ShoppingCart类,它包含一个List<Product>来存储购物车中的商品。如果直接暴露List<Product>,可能会导致外部对象直接操作购物车中的商品,从而破坏封装性。

public class ShoppingCart {
    private List<Product> products;

    public List<Product> getProducts() {
        return products;
    }
}

改进方案

可以通过提供只读的方法来封装内部细节:

public class ShoppingCart {
    private List<Product> products;

    public List<Product> getProducts() {
        return Collections.unmodifiableList(products);
    }

    public void addProduct(Product product) {
        products.add(product);
    }

    public void removeProduct(Product product) {
        products.remove(product);
    }
}

这样,外部对象只能通过ShoppingCart提供的方法来操作商品,而不需要了解List<Product>的内部结构。

如何在实际开发中应用迪米特法则

1. 识别对象的边界

在设计类时,首先要明确类的职责和边界。一个类应当只负责自己的职责,而不应当涉及其他类的内部细节。通过识别对象的边界,可以有效地应用迪米特法则。

2. 使用中介模式

当多个对象之间存在复杂的依赖关系时,可以引入中介对象来管理这些依赖关系。中介对象充当了各个对象之间的协调者,从而减少了对象之间的直接依赖。

3. 封装内部状态

在设计类时,应当尽量封装内部状态,避免将内部状态直接暴露给外部对象。通过提供只读的方法或只读的接口,可以有效地保护内部状态,从而遵循迪米特法则。

4. 遵循“最少知识”原则

在编写代码时,始终牢记“最少知识”原则。一个对象应当只与直接的朋友通信,而不应当与朋友的朋友通信。通过遵循这一原则,可以减少对象之间的依赖关系,从而提高系统的灵活性和可维护性。

总结

迪米特法则作为六大设计原则之一,强调对象之间的松耦合,通过限制对象之间的通信来降低系统的复杂性。遵循迪米特法则可以提高系统的模块化程度、降低耦合度、增强可测试性。在实际开发中,通过识别对象的边界、使用中介模式、封装内部状态以及遵循“最少知识”原则,可以有效地应用迪米特法则,构建高质量、可维护的软件系统。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫代理API的全面解析:让数据抓取更高效

在大数据时代&#xff0c;网络爬虫已经成为收集和分析数据的重要工具。然而&#xff0c;频繁的请求会导致IP被封禁&#xff0c;这时候爬虫代理API就显得尤为重要。本文将详细介绍爬虫代理API的作用、优势及如何使用&#xff0c;帮助你更高效地进行数据抓取。 什么是爬虫代理AP…

注解(Java程序的一种特殊“注释”,用于工具处理的标注)

1.使用注解 a.含义 i.注解是放在类&#xff0c;字段&#xff0c;方法&#xff0c;参数前的一种特殊“注释”。 ii.注释会被编译器直接忽略&#xff0c;注解则可以被编译器打包带进class文件&#xff0c;因此&#xff0c;注解是一种用于标注的“元数据”。 iii…

设计模式之建造者模式(通俗易懂--代码辅助理解【Java版】)

文章目录 设计模式概述1、建造者模式2、建造者模式使用场景3、优点4、缺点5、主要角色6、代码示例&#xff1a;1&#xff09;实现要求2&#xff09;UML图3)实现步骤&#xff1a;1&#xff09;创建一个表示食物条目和食物包装的接口2&#xff09;创建实现Packing接口的实体类3&a…

NeMo Curator 整理用于 LLM 参数高效微调的自定义数据集

目录 概述 预备知识 定义自定义文档构建器 下载数据集 解析和迭代数据集 将数据集写入 JSONL 格式 使用文档构建器加载数据集 使用现有工具统一 Unicode 格式 设计自定义数据集过滤器 编辑所有个人识别信息 添加指令提示 整合管线 概述 出于演示目的&#xff0c;本…

QXml 使用方法

VS2019 QT 编译工具链问题解决 使用winqtdeploy.exe 打包环境就可以正常运行&#xff0c;缺少某一个运行库引起的 简易使用python脚本编译运行 Python3 中的 slots 和 QT 中的 slots 宏定义重复, 放在不同的文件中进行调用可以避免 还是比较习惯从源码包引入&#xff08;方便定…

相机光学(三十七)——自动对焦原理

1.自动对焦的三种方式 目前在手机上采用的自动对焦系统包括反差对焦、相位对焦和激光对焦三种方案&#xff0c;下面我们来看一下它们的工作原理和相互之间的区别是什么。 1.1反差对焦【CDAF】- Contrast Detection Auto Focus 反差对焦是目前普及率最高、使用最广泛、成本相对…

哈希表、算法

哈希表 hash&#xff1a; 在编程和数据结构中&#xff0c;"hash" 通常指的是哈希函数&#xff0c;它是一种算法&#xff0c;用于将数据&#xff08;通常是字符 串&#xff09;映射到一个固定大小的数字&#xff08;哈希值&#xff09;。哈希函数在哈希表中尤为重要…

视觉SLAM ch5——相机与图像

一、单目模型 前言&#xff1a;本大标题下1~4部分讲述的都是单目针孔相机 SLAM的数学本质可以抽象为运动方程&#xff08;x&#xff09;和观测方程&#xff08;z&#xff09;&#xff08;书上的第二部分&#xff09; 教材第二章截图 书中P24页截图 其中的未知量为xk&#xff…

Golang | Leetcode Golang题解之第398题随机数索引

题目&#xff1a; 题解&#xff1a; type Solution []intfunc Constructor(nums []int) Solution {return nums }func (nums Solution) Pick(target int) (ans int) {cnt : 0for i, num : range nums {if num target {cnt // 第 cnt 次遇到 targetif rand.Intn(cnt) 0 {ans …

Gin-封装自动路由

O.0 思路一、API二、控制层三、自动路由核心四、分组路由外加中间件使用 思路 由于Java转Go直接使用的goframe框架&#xff0c;然学习Gin时觉得一个接口一个路由太麻烦&#xff0c;于是有了...1、在请求结构体中采用标签的形式&#xff0c;直接给出路由和请求方式 2、在控制层…

Golang开发之路

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Go协程及并发锁应用指南

概念 协程&#xff08;Goroutine&#xff09;是Go语言独有的并发体&#xff0c;是一种轻量级的线程&#xff0c;也被称为用户态线程。相对于传统的多线程编程&#xff0c;协程的优点在于更加轻量级&#xff0c;占用系统资源更少&#xff0c;切换上下文的速度更快&#xff0c;不…

pyflink 安装和测试

FPY Warning! 安装 apache-Flink # pip install apache-Flink -i https://pypi.tuna.tsinghua.edu.cn/simple/ Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple/ Collecting apache-FlinkDownloading https://pypi.tuna.tsinghua.edu.cn/packages/7f/a3/ad502…

【Docker部署ELK】(7.15)

1、拉取镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.0 docker pull docker.elastic.co/kibana/kibana:7.15.0 docker pull docker.elastic.co/logstash/logstash:7.15.02、配置文件&#xff08;解压资源到D盘DOCKER目录下&#xff09; 2.1 配置文件…

什么是java的spi?

Java SPI&#xff08;Service Provider Interface&#xff09;是一种提供服务发现机制的设计模式&#xff0c;允许在运行时动态地发现、加载和替换服务的实现。SPI机制的核心思想是&#xff1a;通过接口定义服务&#xff0c;并且使用外部的实现类来提供该服务的具体功能。 目录…

【delphi】判断多显示器下,程序在那个显示器中

在 Delphi 中&#xff0c;如果你的电脑连接了多个显示器&#xff0c;可以通过以下步骤判断某个程序在哪个显示器上运行。 方法概述&#xff1a; 获取程序窗口的位置&#xff08;例如窗体的 Left、Top 坐标&#xff09;。使用 Screen.MonitorFromWindow 函数来确定该窗口所属的…

【STM32】单级与串级PID控制的C语言实现

【STM32】单级与串级PID的C语言实现 前言PID理论什么是PIDPID计算过程PID计算公式Pout、Iout、Dout的作用单级PID与串级PID PID应用单级PID串级PID 前言 笔者最近在学习PID控制器&#xff0c;本文基于Blog做以总结。CSDN上已有大量PID理论知识的优秀文章&#xff0c;因此本文将…

短信验证码倒计时 (直接复制即可使用) vue3

需求&#xff1a; 要实现一个获取验证码的需求&#xff0c;点击获取验证码60秒内不可以重复点击&#xff0c;方式有两种可以直接复制使用&#xff1b; 效果图 实现方案 方案1 (单个文件内使用比较推荐) <el-button :disabled"codeDisabled" click.stop"h…

【在Linux世界中追寻伟大的One Piece】网络命令|验证UDP

目录 1 -> Ping命令 2 -> Netstat命令 3 -> Pidof命令 4 -> 验证UDP-Windows作为client访问Linux 4.1 -> UDP client样例 1 -> Ping命令 Ping命令是一种网络诊断工具&#xff0c;它使用ICMP(Internet Control Message Protocol&#xff0c;互联网控制消…

redis常见的数据类型?

参考&#xff1a;一文读懂Redis五种数据类型及应用场景 - 知乎 (zhihu.com) String 类型 String 类型&#xff1a;Redis 最基本的数据类型&#xff0c;它是二进制安全的&#xff0c;意味着你可以用它来存储任何类型的数据&#xff0c;如图片、序列化对象等。使用场景&#xff…