Java设计模式-迪米特法则

2023-11-08

迪米特法则 【Low Of Demeter】

  定义:一个对象应该对其他对象保持最少的了解。

  问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。

  解决方案:尽量降低类与类之间的耦合。

  自从我们接触编程开始,就知道了软件编程的总的原则:低耦合,高内聚。无论是面向过程编程还是面向对象编程,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。低耦合的优点不言而喻,但是怎么样编程才能做到低耦合呢?那正是迪米特法则要去完成的。

  迪米特法则(Law of Demeter,LoD)又叫作最少知识原则(Least Knowledge Principle,LKP),产生于 1987 年美国东北大学(Northeastern University)的一个名为迪米特(Demeter)的研究项目,由伊恩·荷兰(Ian Holland)提出,被 UML 创始者之一的布奇(Booch)普及,后来又因为在经典著作《程序员修炼之道》(The Pragmatic Programmer)提及而广为人知。

  迪米特法则的定义是:只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

  通俗的来讲,就是一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供的public方法,不对外泄漏任何信息。迪米特法则还有一个更简单的定义:只与直接的朋友通信。首先来解释一下什么是直接的朋友:迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。

迪米特法则的实现方法
  从迪米特法则的定义和特点可知,它强调以下两点:

  1. 从依赖者的角度来说,只依赖应该依赖的对象。
  2. 从被依赖者的角度说,只暴露应该暴露的方法。

  所以,在运用迪米特法则时要注意以下 6 点。

  1. 在类的划分上,应该创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。
  2. 在类的结构设计上,尽量降低类成员的访问权限。
  3. 在类的设计上,优先考虑将一个类设置成不变类。
  4. 在对其他类的引用上,将引用其他对象的次数降到最低。
  5. 不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。
  6. 谨慎使用序列化(Serializable)功能。

明星与经纪人的关系实例

  明星由于全身心投入艺术,所以许多日常事务由经纪人负责处理,如与粉丝的见面会,与媒体公司的业务洽淡等。这里的经纪人是明星的朋友,而粉丝和媒体公司是陌生人,所以适合使用迪米特法则,其类图如图
明星与经纪人的关系图
代码如下

package test;

public class test {

    public static void main(String[] args)
    {
        Agent agent=new Agent();
        agent.setStar(new Star("胡歌"));
        agent.setFans(new Fans("粉丝"));
        agent.setCompany(new Company("上海唐人电影制作有限公司"));
        agent.meeting();
        agent.business();
    }
}
//经纪人
class Agent
{
    private Star myStar;
    private Fans myFans;
    private Company myCompany;
    public void setStar(Star myStar)
    {
        this.myStar=myStar;
    }
    public void setFans(Fans myFans)
    {
        this.myFans=myFans;
    }
    public void setCompany(Company myCompany)
    {
        this.myCompany=myCompany;
    }
    public void meeting()
    {
        System.out.println(myFans.getName()+"与明星"+myStar.getName()+"见面了。");
    }
    public void business()
    {
        System.out.println(myCompany.getName()+"与明星"+myStar.getName()+"洽淡业务。");
    }
}
//明星
class Star
{
    private String name;
    Star(String name)
    {
        this.name=name;
    }
    public String getName()
    {
        return name;
    }
}
//粉丝
class Fans
{
    private String name;
    Fans(String name)
    {
        this.name=name;
    }
    public String getName()
    {
        return name;
    }
}
//媒体公司
class Company
{
    private String name;
    Company(String name)
    {
        this.name=name;
    }
    public String getName()
    {
        return name;
    }
}

运行结果如下:

粉丝与明星胡歌见面了。
上海唐人电影制作有限公司与明星胡歌洽淡业务。

  迪米特法则的优点
  迪米特法则要求限制软件实体之间通信的宽度和深度,正确使用迪米特法则将有以下两个优点。

  • 降低了类之间的耦合度,提高了模块的相对独立性。
  • 由于亲合度降低,从而提高了类的可复用率和系统的扩展性。

  但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,例如本例中,明星就是通过经纪人这个“中介”来与媒体公司、粉丝发生联系的。过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以,在釆用迪米特法则时需要反复权衡,确保高内聚和低耦合的同时,保证系统的结构清晰。

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

Java设计模式-迪米特法则 的相关文章

  • 如何对由 keycloak 保护的 SpringBoot 控制器进行单元测试?

    我知道已经有类似的问题了here https stackoverflow com questions 49144953 mocking a keycloak token for testing a spring controller and
  • 寻找下一个素数的最佳方法(Java)

    我被要求编写一个程序以最佳方式找到下一个素数 我编写了这段代码 但找不到最佳答案 有什么建议么 public static int nextPrime int input input now find if the number is pr
  • Java 中字符串的最大长度 - 调用 length() 方法

    In Java 最大尺寸 a 是多少String对象可能有 指的是length 方法调用 我知道length 返回 a 的大小String as a char 考虑到String http docs oracle com javase 7
  • 范围内的春季活动可能吗?

    Spring 事件机制支持发布应用程序事件并通过 Spring 组件监听这些事件 EventListener注解 但是 我在 中找不到有关在特定范围内发送事件的任何信息文档 https docs spring io spring docs
  • 如何在gradle中执行jar文件?

    当我使用 ant 构建我的 android 项目时 我需要这样的任务
  • 通过 Java Spring 构建 sitemap.xml [重复]

    这个问题在这里已经有答案了 我正在通过 Spring MVC 构建 sitemap xml XmlRootElement name urlset public class XmlUrlSet XmlElements XmlElement n
  • 在总是抛出方法之后如何检测死代码?

    考虑以下代码 Test public void testDeadCode letsThrow System out println will never be reached private final void letsThrow thr
  • 谷歌地图返回空指针异常

    当我尝试在片段上显示地图时 它返回空指针异常 我已将所有内容添加到清单中的每个权限中 我正在附加片段文件 XML 文件和日志目录 Chatffragment java public class ChatFragment extends Fr
  • 如何在 Java 中从任意基数转换为基数 10

    我是 Java 新手 我想编写一个程序 仅使用算术运算将基数 2 3 4 5 6 7 8 9 16 转换为基数 10 我已经完成了从键盘读取字符串 如果数字是十六进制 并将其转换为整数 之后我做了一个 while 循环 将数字分割为数字并将
  • Java中如何存储profile?

    我仍在学习 Java 的诀窍 如果有一个明显的答案 我很抱歉 我有一个占用大量内存的程序 我想找到一种方法来减少其使用 但是在阅读了许多 SO 问题后 我认为在开始优化它之前我需要证明问题出在哪里 这就是我所做的 我在程序的开头添加了一个断
  • 如何在 Java 中通过 TLS v.1.2 创建安全的 TCP 连接

    我想通过 TLS v1 2 在两个系统之间创建通信 其中包含的信息是保密的 我想避免 https Web 服务调用 而直接想在 TCP 层执行消息交换 您能否建议如何实现此功能 以便我可以通过 TLS v1 2 安全地传输数据 EDIT 阅
  • Java 字节码中循环的检测 - 区分后沿类型

    背景 在提出问题之前 我想声明我已检查以下链接 识别java字节码中的循环 https stackoverflow com questions 6792305 identify loops in java byte code Java 字节
  • Hibernate添加带有子实体id的实体

    我的对象 状态 java Entity Table name STATE public class State Id GeneratedValue strategy GenerationType AUTO private Long id C
  • 通过反思思考工厂设计模式

    我正在对工厂模式进行研发 我开发了下面的代码 现在我知道子类是 Dog 和 Cat 但是如果我想通过在 main 中传递类名来通过反射实现同样的事情 请告诉我该怎么做 爪哇 public abstract class Animal publ
  • Hibernate:单表中的父/子关系

    我几乎没有看到任何关于以下与 Hibernate 相关问题的提示 这涉及使用具有父子关系的单个数据库表来实现继承 与自身的关系 例如 CREATE TABLE Employee empId BIGINT NOT NULL AUTO INCR
  • 如何使用 NetBeans 导入 Jackson Core JacksonFactory?

    请参阅固定导入声明的链接问题 我将在尝试 Netbeans 后更新这个问题 下面使用 Netbeans 一切应该建立 https github com NICKSAUNDERS sheets 然而 这个问题是针对 Netbeans 的 寻找
  • 在Java中解析包含multipart/form-data请求体的字符串

    问题陈述 我认为标题说明了一切 我正在寻找解析 a 的方法String包含 multipart form data HTTP 请求的正文部分 IE 字符串的内容看起来像这样 xyzseparator blah Content Disposi
  • 从邮件服务器读取发送的邮件

    我知道如何从 INBOX 文件夹中检索邮件 但现在我想从 SENT ITEMS 文件夹中检索邮件 我正在使用 imap 检索数据 让我知道我应该在此函数中传递什么参数才能从 SENT ITEMS 文件夹中获取邮件Folder folder
  • 多个事件分派线程

    我是 Java Swing 新手 我的问题与事件队列和调度线程相关 我读到可以有多个事件队列 每个队列应用上下文 http www java2s com Open Source Java Document 6 0 JDK Modules s
  • @Transactional 方法调用另一个没有 @Transactional 注解的方法?

    我在 Service 类中看到了一个方法 该方法被标记为 Transactional 但它还调用同一类中的一些其他方法 这些方法未标记为 Transactional 这是否意味着对单独方法的调用导致应用程序打开与数据库的单独连接或挂起父事务

随机推荐

  • Linux域名解析得到ip地址

    Linux下域名解析得到ip地址代码如下 include
  • Redis(持续完善....)

    1 Redis结构 Redis是一款基于内存的NoSQL数据存储服务 是非关系型的 是使用K V结构进行存储的 gt lt 基于内存 读写数据均在内存中直接操作 gt
  • 高性能Mysql——SQL执行计划分析(EXPLAIN)

    文章目录 通过EXPLAIN进行执行计划分析 ID select type Table Partitions Type Extra possible keys Key key len Ref Rows Filtered EXPLAIN不能完
  • int与float深入理解

    别在int与float上栽跟头 int与float是我们每天编程都用的两种类型 但是我们真的足够了解它们吗 昨天在博客园看到一个比较老的笑话 昨天晚上下班回家 一民警迎面巡逻而来 突然对我大喊 站住 民警 int 类型占几个字节 我 4 个
  • 记录Maven的相关操作(笔记整理)

    一 安装 我使用的是免安装版的 直接解压缩就可以使用 二 配置环境变量 打开环境变量配置 右键计算机 属性 高级系统设置 高级 环境变量 在系统变量中配置 配置MAVEN HOME 在系统变量中新建 变量名MAVEN HOME 变量值 ma
  • Swoole - 为什么说Swoole中小型企业微服务的首选技术方案

    概述 Swoole的出现 使PHP语言不再局限于传统的 Web领域 对中小企业有很好的支持 有一些企业盲目的追求微服务和K8s 我真诚建议不要轻易上微服务 上了你才知道这里面的辛酸 高成本 低效率会拖碎整个团队 研究中小企业的提效 节省成本
  • sql中on条件和where条件查询结果一样嘛?

    如果使用 join不会有影响 但是 在使用left join时 on和where条件的区别如下 on条件是在生成临时表时使用的条件 它不管on中的条件是否为真 都会返回左边表中的记录 where条件是在临时表生成好后 再对临时表进行过滤的条
  • 【RuoYi-Vue-Plus】学习笔记 28 - 数据脱敏 Json 序列化工具 SensitiveJsonSerializer(Jackson 源码)

    文章目录 前言 参考目录 功能代码实现及测试 1 数据脱敏注解 Sensitive 2 脱敏策略枚举 SensitiveStrategy 3 脱敏 Json 序列化器 SensitiveJsonSerializer 4 测试类 TestSe
  • 大数据面试题集

    史上最全大数据面试题 V3 1 特辑 目录 一 数据仓库 1 维表和宽表的考查 主要考察维表的使用及维度退化手法 2 数仓表命名规范 3 拉链表的使用场景 4 数据库和数据仓库有什么区别 5 有什么维表 时间维表 用户维表 产品维表 合同维
  • PHP 三元 !empty 而不是评估为真或假 可用isset()

    是否可以使用速记三元来检查变量是否已设置 而不是是否计算结果为零或非零 例如 我试过 var 0 echo string var string false 2 但由于前两个表达式的计算结果均为 0 或 false 因此显示为 2 我认为也许
  • Netty4 websocket 开启服务端并设置IP和端口号

    一 环境也就是POM文件
  • Python学习(4)证件照底色变换

    Python学习 4 证件照底色变换 前言 一 Python准备 二 Python仿真 三 仿真结果 四 小结 前言 随着人工智能研究的不断兴起 Python的应用也在不断上升 由于Python语言的简洁性 易读性以及可扩展性 特别是在开源
  • Java面向对象三大特性(封装、继承、多态)

    文章目录 前言 一 封装 1 封装的概念 2 private实现封装 3 getter和setter方法 4 封装的好处 二 继承 1 继承的概念 2 extends实现继承 3 super 关键字 Object 4 访问权限 1 priv
  • 蓝桥杯单片机第十四届第三次模拟题

    题目 Main c include
  • [数值计算-12]:什么是函数逼近:插值、拟合、回归

    作者主页 文火冰糖的硅基工坊 https blog csdn net HiWangWenBing 本文网址 https blog csdn net HiWangWenBing article details 119901220 目录 第1章
  • ISO-15118 -1,2,3,4,5,6,8,9,20【最新版】1~20,国际标准分类中,ISO15118涉及到电车、道路车辆装置

    ISO 15118 本专题涉及ISO15118的标准有 国际标准分类中 ISO15118涉及到电车 道路车辆装置 在中国标准分类中 ISO15118涉及到无轨电车牵引供电 交通管理综合 电子 电气设备 公路工程 ISO 15118 20 2
  • 【Java学习笔记】异常处理

    一 异常分类 1 可检查的异常 编译时检查 必须捕捉或声明 可查异常虽然是异常状况 但在一定程度上它的发生是可以预计的 而且一旦发生这种异常状况 就必须采取某种方式进行处理 2 不可检查的异常 编译时不受检查 不需要捕捉或声明 包括erro
  • 主板电源开关接口图解_主板跳线接法示意图,超详细适合DIY新手

    现在DIY自己装机已经很简单了 网上的教程各种各样 也不用专门去电脑城找专业人士来装了 只需要购买好硬件即可 不过 在组装电脑时有一个步骤是很难的 就是主板跳线或者说机箱里面各种线怎么接 下面就给大家说说主板跳线接法 一 开关机跳线和指示灯
  • linux命令总结dd命令详解

    dd 用指定大小的块拷贝一个文件 并在拷贝的同时进行指定的转换 注意 指定数字的地方若以下列字符结尾 则乘以相应的数字 b 512 c 1 k 1024 w 2 参数注释 if 文件名 输入文件名 缺省为标准输入 即指定源文件 lt if
  • Java设计模式-迪米特法则

    迪米特法则 Low Of Demeter 定义 一个对象应该对其他对象保持最少的了解 问题由来 类与类之间的关系越密切 耦合度越大 当一个类发生改变时 对另一个类的影响也越大 解决方案 尽量降低类与类之间的耦合 自从我们接触编程开始 就知道