设计原则之【迪米特法则】,非礼勿近

2023-05-16

文章目录

  • 一、什么是迪米特法则
    • 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);
  }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计原则之【迪米特法则】,非礼勿近 的相关文章

  • 怎么成为一名架构师?架构师第一步。基层开发人员逆袭成为架构师真的很难吗?

    文章目录 写在前面一 企业需要什么样的架构师1 从招聘软件上了解2 架构师的主要职责与能力 二 成为一名架构师很难吗1 架构师的定义2 当前大部分开发团队的现状3 为什么要有架构师4 技术人员如何自我突破 三 晨钟暮鼓的几句话 写在前面 一
  • MVN打包报错:在类路径或引导类路径中找不到程序包 java.lang

    现象 同一个Springboot项目在windows下mvn打包正常 xff0c 在linux下打包就失败了 打包命令如下 xff1a mvn clean package Dmaven test skip span class token
  • archlinux按键交换

    原本以为需要安装第三方软件 才能实现 xff0c 发现KDE中自带这个功能的设置 直接使用就好 左Ctrl与左Win交换 默认带了很多方案 xff0c 正好就有能满足我的需要的
  • archlinux i3平铺桌面学习笔记

    安装 pacman S i3 选择全部安装 按键配置 我的想法是全默认 xff0c 习惯一下默认的按键风格 修改默认terminal bindsym span class token variable mod span 43 Return
  • PostMan测试若依修改接口

    说来惭愧 xff0c 我使用postman调试修改接口时 xff0c 竟然耗了半小时才搞定 决定文档记录一下 Headers 设置 Authorization Bearer eyJhbGciOiJIUzUxMiJ9 eyJsb2dpbl91
  • Windows 禁用WIn+L锁定系统快捷键

    因为我在windows中使用虚拟机中的Linux做主力开发机用 有时会用到win 43 l这个按键 会导致Windows直接锁屏了 所以我想把这个功能禁用掉 方法 按 Win 43 R 打开运行对话框输入 regedit 然后按回车 xff
  • archlinux按键映射按键自定义

    安装xorg span class token function sudo span pacman S xorg 直接选择全部安装 xmodmap span class token comment 显示按键信息 span xmodmap p
  • IntelliJ IDEA包自动导入设置

    IDEA的默认设置是 xff0c 当需要导包的时候会有个提示 xff0c 这时按Alt xff0b Enter可以手动导入包 这些年一直这么用 xff0c 也习惯了 但是用了一些其他的IDE开发工具边写代码边自动导入 xff0c 用了以后挺
  • kitty终端使用笔记

    简介 kitty是一个免费的开源 图形处理单元 GPU 加速 2 3 终端仿真器 xff0c 适用于Linux和macOS xff0c 专注于性能和功能 kitty 是用C和Python编程语言混合编写的 xff0c 它是少数支持 GPU
  • i3status配置笔记

    默认配置 最近一直在忙于写代码 xff0c i3status安装以后就没有做过任何配置 显示了一些我并不关心的内容 帮助文档 https i3wm org docs i3status html 创建配置文件 mkdir span class
  • Mybatis (ParameterType) 如何传递多个不同类型的参数

    在一些场景下 xff0c 传参是需要多个参数的 一个参数不太够用 xff0c 如 xff1a parameterType 61 34 ImGroup 34 最开始的想法是封装一个专用用来当参数的对象 xff0c 把多个对象包装到一起 xff
  • UML类图使用介绍

    文章目录 一 UML图1 什么是UML图2 类图概述3 类图的作用 二 类的表示方式举个栗子 三 类与类之间关系的表示方式1 关联关系 xff08 1 xff09 单向关联 xff08 2 xff09 双向关联 xff08 3 xff09
  • 没有U盘纯硬盘安装linux之Archlinux

    安装系统用U盘是很方便的 xff0c 无奈我的U盘莫名奇妙的坏了 因为疫情影响 xff0c 买个U盘要挺久时间才能到达 所以我就想能不能使用硬盘来安装linux系统呢 试试吧 xff01 一方面可以省下一个U盘的钱 xff0c 另一方面 x
  • 【Java】微信聊天记录特定词过滤

    微信聊天记录特定词过滤 通常微信聊天记录中包含文本 图片 语音 视频等 xff0c 这些数据显然需要用一个统一的数据结构存储和读取数据 然后把聊天记录中文本数据扣出 寻找是否含指定词 本题选做 Message类 xff0c 描述一条聊天数据

随机推荐

  • linux远程windows桌面

    remmina Remmina 是用 GTK 编写的远程桌面客户端 xff0c 来自 FreeRDP 项目 它支持以下协议 xff1a SSH VNC RDP NX XDMCP 图形化的操作界面用起来很简单方便 安装 span class
  • i3wm nm-applet每次开机都要输入wifi密码的解决办法

    在KDE中使用 xff0c 每次开机不需要输入wifi密码就可以直接上网了 为了提供开发效率 我尝试使用i3wm做为开发环境 但是每次开机都要输入wifi密码很不方便 解决办法 查了一下wiki 好像是因为没有安装GNOME Keyring
  • MySQL limit分页

    之前写了篇 SpringBoot中封装jdbc工具类 xff0c 最近在使用的过程中发现没有分页功能 所以就打算在封装一下分页算法 相关文章 xff1a https blog csdn net lxyoucan article detail
  • i3wm中Chrome不保存密码

    最近切到i3wm中发现一个问题 xff0c 在这个环境下使用Chrome密码不会被保存 xff0c 也无法使用密码自动填充 使用起来非常的不方便 然而在KDE中使用chrome一切正常 xff0c 一切到i3wm就无法使用了 而且所有网站都
  • linux 开机自动登录i3wm

    最近在我的物理机上打算使用archlinux当主力机 但是因为我这台笔记本电脑最近刚发布的 xff0c 安装archlinux无法正确识别笔记本电脑自带的键盘 只能外接usb键盘 xff0c 或者使用蓝牙键盘了 因为我的usb键盘过于厚重
  • linux命令行连接蓝牙键盘

    在KDE的图形界面连接蓝牙设备非常的方便 xff0c 图形化点点就行了 图形化连接 基础 span class token comment 安装 span span class token function sudo span pacman
  • Java爬虫html解析神器Jsoup

    jsoup是一个用于解析 提取 操作HTML的开源Java函式库 在我眼里就是一个java版本的jquery xff0c 非常强大 xff01 xff01 xff01 jsoup在2009年由亚马逊软件开发经理Jonathan Hedley
  • kitty终端ranger预览图片

    之前在macOS中使用iterm2终端用ranger预览图片正常 最近切到archlinux了 xff0c 使用kitty终端模拟器 也想实现ranger中预览图片 相关阅读 xff1a 终端中的文件管理器ranger 视频 https b
  • 设计原则之【接口隔离原则】,我只做我能做的事

    文章目录 一 什么是接口隔离原则二 实例三 总结接口隔离原则与单一职责原则的区别 一 什么是接口隔离原则 接口隔离原则 xff08 Interface Segregation Principle ISP xff09 是指用多个专门的接口 x
  • java: You aren‘t using a compiler supported by lombok

    在学习这个RuoYi Vue Process项目的时候 xff0c 编译报错 https gitee com calvinhwang123 RuoYi Vue Process 报错信息 编译警告信息 java You aren 39 t u
  • i3wm中截图软件flameshot deepin-screenshot

    archlinux中使用i3wm窗口管理器 xff0c 有什么好的截图软件呢 xff1f 环境 先看一下我的环境信息 xff1a span class token variable span class token variable 96
  • i3wm开启自动设置显示器顺序方向分辨率

    多屏使用linux系统时 xff0c 在KDE中设置好显示器的分辨率和显示器顺序 下次开机启动可以记住之前的配置 在i3桌面环境中 xff0c 每次开机都要重新设置一下 xff0c 这就很不人性化了 于是我想找个解决办法 xrandr 使用
  • 汉化Swagger springfox-swagger-ui-2.9.2.jar

    在若依的文档中看到汉化swagger的方法 xff0c 自己尝试怎么也不能成功 后来经过查阅各种文档发现 若依文档中提到的方法仅对 springfox swagger ui 2 7版本生效 对springfox swagger ui 2 9
  • Swagger基本示例

    类注解 span class token annotation punctuation 64 RestController span span class token annotation punctuation 64 RequestMap
  • Spring boot redis java.io.IOException: 远程主机强迫关闭了一个现有的连接

    现象 在测试环境部署的若依版本 xff0c 经常会报如下的错误 而我在开发环境基本没有遇到过 span class token number 16 span span class token operator span span class
  • thunderbird重复的已发送

    最近转到Linux下办公 xff0c 邮件客户端选用的Thunderbird 总体来说还是能适应的 但是在用的过程中发现很次发送信件后 xff0c 发件箱会有一个重复的邮件 我猜测可能是用于备份的 但是我的使用场景几乎用不到这样的功能 xf
  • linux keynav 鼠标可以扔掉了键盘控制鼠标

    我是一个vim用户 xff0c 喜欢使用键盘操作大部分的事情 无奈现在很多软件从设计之初就是为了鼠标设计的 就导致有些时候不得不使用鼠标 那么退一步讲 xff0c 能否使用键盘临时控制一下鼠标呢 xff1f 这样就可以进一步减少鼠标的使用了
  • mysql数据库的导出与导入

    在开发工作中和运维工作中 xff0c 数据库的备份与还原是很常见的工作 之前的工作中我使用oracle更多 xff0c mysql的备份工作参与的比较少 记录一下 xff0c 加深一下印象 准备工作 安装mysql客户端 xff0c 我喜欢
  • linux Windows双系统时间不一致的解决办法

    原因 电脑系统中有两个时间 xff1a 硬件时间 xff1a 保存在主板中 xff0c 信息比较少没时区 夏令时的概念 系统时间 xff1a 又系统维护 xff0c 独立于硬件时间 xff0c 拥有时区 夏令时等信息 系统时间又因为系统的不
  • 设计原则之【迪米特法则】,非礼勿近

    文章目录 一 什么是迪米特法则1 理解迪米特法则2 如何理解 高内聚 松耦合 xff1f 二 实例1 实例12 实例2 一 什么是迪米特法则 迪米特原则 xff08 Law of Demeter LoD xff09 是指一个对象应该对其他对