设计原则之【迪米特法则】

news2024/10/7 2:32:15

文章目录

  • 一、什么是迪米特法则
    • 1、理解迪米特法则
    • 2、如何理解“高内聚、松耦合”?
  • 二、实例
    • 1、实例1
    • 2、实例2

一、什么是迪米特法则

迪米特原则(Law of Demeter LoD)是指一个对象应该对其他对象保持最少的了解,又叫最少知道原则(Least Knowledge Principle,LKP),尽量降低类与类之间的耦合。迪米特原则主要强调只和朋友交流,不和陌生人说话。出现在成员变量、方法的输入、输出参数中的类都可以称之为成员朋友类,而出现在方法体内部的类不属于朋友类。

其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。

1、理解迪米特法则

不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。迪米特法则是希望减少类之间的耦合,让类越独立越好。每个类都应该少了解系统的其他部分。一旦发生变化,需要了解这一变化的类就会比较少。

2、如何理解“高内聚、松耦合”?

“高内聚、松耦合”是一个非常重要的设计思想,能够有效提高代码的可读性和可维护性,缩小功能改动导致的代码改动范围。“高内聚”用来指导类本身的设计,“松耦合”用来指导类与类之间依赖关系的设计。

所谓高内聚,就是指相近的功能应该放到同一个类中,不相近的功能不要放到同一类中。相近的功能往往会被同时修改,放到同一个类中,修改会比较集中。所谓松耦合指的是,在代码中,类与类之间的依赖关系简单清晰。即使两个类有依赖关系,一个类的代码改动也不会或者很少导致依赖类的代码改动。

二、实例

1、实例1

现在来设计一个权限系统,TeamLeader需要查看目前发布到线上的课程数量。这时候,TeamLeader要找到员工 Employee 去进行统计,Employee 再把统计结果告诉 TeamLeader。接下来我们还是来看代码:

public class Course {
}

public class Employee{
	public void checkNumberOfCourses(List<Course> courseList){
		System.out.println("目前已发布的课程数量是:" + courseList.size());
	}
}

public class TeamLeader{
	public void commandCheckNumber(Employee employee){
		List<Course> courseList = new ArrayList<Course>();
		for (int i= 0; i < 20 ;i ++){
			courseList.add(new Course());
		}
		employee.checkNumberOfCourses(courseList);
	}
}

public static void main(String[] args) {
	TeamLeader teamLeader = new TeamLeader();
	Employee employee = new Employee();
	teamLeader.commandCheckNumber(employee);
}

写到这里,其实功能已经都已经实现,代码看上去也没什么问题。根据迪米特原则,TeamLeader只想要结果,不需要跟 Course 产生直接的交流。而 Employee 统计需要引用 Course 对象。TeamLeader和 Course 并不是朋友,从下面的类图就可以看出来:
在这里插入图片描述
下面来对代码进行改造:

public class Employee {
	public void checkNumberOfCourses(){
		List<Course> courseList = new ArrayList<Course>();
		for (int i= 0; i < 20 ;i ++){
			courseList.add(new Course());
		}
		System.out.println("目前已发布的课程数量是:"+courseList.size());
	}
}

public class TeamLeader {
	public void commandCheckNumber(Employee employee){
		employee.checkNumberOfCourses();
	}
}

再来看下面的类图,Course 和 TeamLeader 已经没有关联了。
在这里插入图片描述
迪米特法则的核心是降低类之间的耦合。
但是要注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系,并不是要求完全没有依赖关系。

2、实例2

我们实现一个简化版的搜索引擎爬取网页的功能。代码中包含三个主要的类。其中,NetUtil 类负责底层网络通信,根据请求获取数据;HtmlDownloader 类用来通过 URL 获取网页;Document 表示网页文档,后续的网页内容抽取、分词、索引都是以此为处理对象。

public class NetUtil{
    // 省略属性和其他方法...
    public Byte[] send(HtmlRequest htmlRequest) {
      //...
    }
}
public class HtmlDownloader {
  private NetUtil netUtil;//通过构造函数或IOC注入
  
  public Html downloadHtml(String url) {
    Byte[] rawHtml = netUtil.send(new HtmlRequest(url));
    return new Html(rawHtml);
  }
}
public class Document {
  private Html html;
  private String url;
  
  public Document(String url) {
    this.url = url;
    HtmlDownloader downloader = new HtmlDownloader();
    this.html = downloader.downloadHtml(url);
  }
  //...
}

我们分析一下这三个类,虽然看起来没什么问题,但是仍有优化的空间。

首先看NetUtil类,作为一个工具类,应该尽可能的“通用”,send方法不应该依赖HtmlRequest 。

public class NetUtil {
    // 省略属性和其他方法...
    public Byte[] send(String address, Byte[] data) {
      //...
    }
}

我们修改了NetUtil 类,那么HtmlDownloader 也应该同步修改:

public class HtmlDownloader {
  private NetUtil netUtil;//通过构造函数或IOC注入
  
  public Html downloadHtml(String url) {
  	HtmlRequest htmlRequest = new HtmlRequest(url);
    Byte[] rawHtml = netUtil.send(htmlRequest.getAddress(), htmlRequest.getContent().getBytes());
    return new Html(rawHtml);
  }
}

Document类构造方法中downloadHtml耗时较长,不应该放在构造方法中,影响代码的可测试性;
HtmlDownloader 对象在构造函数中通过 new 来创建,违反了基于接口而非实现编程的设计思想,也会影响到代码的可测试性;
从业务含义上来讲,Document 网页文档没必要依赖 HtmlDownloader 类,违背了迪米特法则。

ublic class Document {
  private Html html;
  private String url;
  
  public Document(String url, Html html) {
    this.html = html;
    this.url = url;
  }
  //...
}
// 通过一个工厂方法来创建Document
public class DocumentFactory {
  private HtmlDownloader downloader;
  
  public DocumentFactory(HtmlDownloader downloader) {
    this.downloader = downloader;
  }
  
  public Document createDocument(String url) {
    Html html = downloader.downloadHtml(url);
    return new Document(url, html);
  }
}

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

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

相关文章

Navicat自动提交的开和关

使用Navicat时&#xff0c;若是自动提交是打开状态&#xff0c;就相当于是自动执行了commit操作&#xff0c;就无法进行回滚操作。 一.相关指令 1.查询Navicat的自动提交开关状态&#xff1a; -- 查询自动提交 ON:是自动提交&#xff0c;即commit ;OFF:不是自动提交&#xf…

Java-注解

文章目录 前言一、概述二、元注解TargetRetentionDocumentedInherited 三、自定义注解四、常用内置注解OverrideDeprecatedSuppressWarnings 前言 注解用于修饰包、类、方法、属性、构造器、局部变量等数据信息&#xff0c;它可以用于创建文档&#xff0c;跟踪代码的依赖性&am…

怎么在VMware ESXi添加NAS存储?

案例&#xff1a;需要将NAS添加到VMware ESXi “我的本地空间不是很多&#xff0c;虚拟机占了我很多空间&#xff0c;但是我有一个NAS&#xff0c;所以我想问一下有没有办法可以让VMware ESXi添加NAS存储来扩展空间&#xff1f;” 网络附加存储&#xff08;NAS&#xff09;设…

2023年6月CDGP数据治理专家认证考试,5月报名及学习

目前6月DAMA-CDGP数据治理专家认证考试开放报名地区有&#xff1a;北京、上海、广州、深圳、长沙、呼和浩特。 目前南京、济南、西安、杭州等地区还在接近开考人数中&#xff0c;打算参加6月考试的朋友们可以抓紧时间报名啦&#xff01;&#xff01;&#xff01; DAMA认证为数据…

为什么每个有影响力的内容创作者都需要一个Kadence WordPress网站

创作者经济正在蓬勃发展&#xff0c;内容创作者正在以前所未有的方式建立受众和收入来源。无论您是在 YouTube、Instagram、TikTok 还是任何其他平台上增加受众&#xff0c;充分利用这些受众变得越来越重要。 Adobe 于 2022 年 8 月发布的一项研究表明&#xff0c;过去 2 年全…

关于加强珠宝玉石类小程序把控的公告

各位小程序开发者为进一步加强小程序的规范管理&#xff0c;保障用户合法权益&#xff0c;平台将对珠宝玉石类小程序加强把控&#xff0c;具体内容如下&#xff1a; 一、 【商家自营-珠宝玉石】类目资质调整 备注&#xff1a;若小程序涉及经营随形加工的原石或摆件相关服务&…

Vue入门简介【第一篇】

大纲 一、Vue介绍 &#x1f334; 1.1 什么是Vue vue是一个构建用户界面UI的渐进式javascript框架&#xff0c;渐进式的框架是指可以一步一步的由浅入深的去使用该框架。 vue官网&#xff1a; https://cn.vuejs.org/ &#x1f334; 1.2 Vue的优点 ⭐️ 1、体积小 压缩后33…

大数据分析就业班课程大纲

大数据分析就业班课程大纲列举&#xff1a; 第一阶段 Mysql从入门到精通/Python从入门到精通课程模块课程内容 MySQL 数据库 数据库概念及其功能介绍、数据库的安装与配置、数据库表的创建及注意事项、数据库的增、删、改、查等操作、多表的关系及查询、多表的…

OSI七层模型中的MAC和PHY

最近做服务器项目在学习MAC和PHY&#xff0c;总结了一些知识点&#xff0c;拿来分享一下 说到MAC和PHY首先要提到OSI七层模型 OSI七层模型 TCP/IP四层模型 对应网络协议 应用层&#xff08;Application&#xff09; 应用层 HTTP、TFTP, FTP, NFS, WAIS、SMTP 表示层&…

【Python入门知识】NumPy 数组排序/过滤,案例+理论讲解

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 数组排序 排序是指将元素按有序顺序排列。 有序序列是拥有与元素相对应的顺序的任何序列&#xff0c;例如数字或字母、升序或降序。 NumPy ndarray 对象有一个名为 sort() 的函数&#xff0c;该函数将对指定的数组进行排…

功率放大器在Lamb波信号波包模型验证研究中的应用

实验名称&#xff1a;窄带激励条件下的兰姆波时域信号参数估计研究 研究方向&#xff1a;Lamb波 测试目的&#xff1a; 基于Lamb波的二阶频散理论&#xff0c;提出了时域信号的波包模型&#xff0c;为全文奠定理论基础。模型考虑两种情况&#xff1a;初始激励以单模态传播和…

【面试】说说什么是 Java 内存模型(JMM)?

文章目录 一、 为什么要有内存模型&#xff1f;1.1. 硬件内存架构1.2. 缓存一致性问题1.3. 处理器优化和指令重排序 二、并发编程的问题三、Java 内存模型3.1. Java 运行时内存区域与硬件内存的关系3.2. Java 线程与主内存的关系3.3. 线程间通信 四、总结 一、 为什么要有内存模…

Java阶段二Day16

Java阶段二Day16 文章目录 Java阶段二Day16SSMSpringBoot简述核心特性创建SpringBoot工程创建工程失败排查 MyBatis框架-注解管理概述MyBatis环境初始化整合MyBatisPojo对象设计Dao接口设计 SSM Spring&#xff1a;Spring是一个轻量级的容器和框架&#xff0c;为开发者提供了一…

沃通“SSL证书+代码签名证书”,防范高仿“钓鱼网站+钓鱼软件”攻击

近日&#xff0c;360发布威胁预警&#xff0c;因监测发现多起利用钓鱼网站对特定用户进行攻击的安全事件&#xff0c;呼吁警惕“高仿”软件安装程序暗藏钓鱼木马。“钓鱼网站钓鱼软件”是非常典型的钓鱼攻击组合&#xff0c;而沃通“SSL证书代码签名证书”能够帮助企业建立安全…

一文带你直观感受,BPM管理系统如何在低代码平台实现搭建

BPM系统&#xff08;英文全称&#xff1a;Business Process Management&#xff0c;翻译后简称BPM&#xff09;即业务流程管理系统&#xff0c;是指对端到端业务流程进行建模、分析和优化&#xff0c;用以实现战略业务目标&#xff0c;其特点是注重流程驱动为核心&#xff0c;实…

通过修改根证书绕过rustls的证书固定机制,抓包解密ssl流量

例子&#xff0c;cloudflare的warp-svc.exe。抓包获取密钥。 用proxifier尝试了一下强行代理&#xff0c;无效&#xff0c;因为proxifier是通过Hook Socket函数方式实现的&#xff0c;但这个程序可能没有用Socket函数进行通信。 之后发现通过nekoray基于gvisor的VPN白名单模式全…

《计算机网络——自顶向下方法》精炼——3.1-3.4.1

“生命在于运动&#xff0c;学习在于不断尝试。”——亚里士多德 文章目录 运输层概述与服务运输层功能运输层概述IP协议UDP和TCP协议 多路复用与多路分解UDPUDP相较于TCP的优点UDP报文段结构检验和可靠数据传输构造可靠数据传输协议 运输层概述与服务 运输层为应用层提供了逻…

2022年宜昌市网络搭建与应用竞赛样题(二)

网络搭建与应用竞赛样题&#xff08;二&#xff09; 技能要求 &#xff08;总分1000分&#xff09; 竞赛说明 一、竞赛内容分布 “网络搭建与应用”竞赛共分三个部分&#xff0c;其中&#xff1a; 第一部分&#xff1a;网络搭建及安全部署项目&#xff08;500分&#xff0…

传统工厂布局数字化的核心因素——智能工厂

近年来很多鼓励企业数字化转型的政策陆续出台&#xff0c;在一定程度上帮助企业减轻数字化转型的成本压力。但是企业数字化转型依然面临着诸多的问题与挑战。主要还是因为大部分企业&#xff0c;特别是制造型企业&#xff0c;数字化进程还在探索阶段&#xff0c;资金、人才、技…

接口自动化测试详解——持续集成流程中不可或缺的一环

B站首推&#xff01;2023最详细自动化测试合集&#xff0c;小白皆可掌握&#xff0c;让测试变得简单、快捷、可靠https://www.bilibili.com/video/BV1ua4y1V7Db 目录 接口自动化测试 Jenkins持续集成 总结 摘要&#xff1a; 在软件开发中&#xff0c;自动化测试已经成为了…