从 “社恐” 思维理解迪米特法则,代码设计原来如此简单!

目录

一、迪米特法则是什么?

二、深入剖析迪米特法则

(一)法则核心:最少知识原则

(二)“朋友圈” 划定:谁是直接朋友?

(三)广义与狭义:法则的不同视角

三、为什么要遵循迪米特法则

(一)降低耦合度,提升模块独立性

(二)提高代码可维护性和可扩展性

(三)增强代码可测试性

四、违反迪米特法则的后果

(一)代码的脆弱性

(二)难以复用的代码

(三)复杂的依赖关系

五、迪米特法则应用案例

(一)学校管理系统案例

(二)电商系统案例

六、实际应用中的权衡

(一)避免过度使用

(二)结合其他设计原则

七、总结


一、迪米特法则是什么?

        迪米特法则(Law of Demeter,LOD),又称为最少知识原则(Least Knowledge Principle,LKP) ,诞生于 1987 年美国东北大学一个名为迪米特的研究项目。它的核心思想非常简单:一个对象应该对其他对象有最少的了解,只和 “朋友” 通信,不和 “陌生人” 说话。

        怎么理解这句话呢?打个比方,你是一个 “社恐” 患者,在社交场合中,你只和自己熟悉的朋友交流,对于那些不认识的陌生人,你不会主动去攀谈。在软件设计里,每个类就像是一个独立的个体,也应该尽量减少与其他不必要类的交互,只和直接关联的类打交道。这样一来,当某个类发生变化时,对其他类的影响就能降到最低,从而提高整个系统的稳定性和可维护性。

        迪米特法则中的 “朋友”,指的是与当前对象有紧密联系的对象,包括以下几种:

  • 当前对象本身;
  • 当前对象的成员对象;
  • 当前对象所创建的对象;
  • 当前方法的参数对象。

        一个对象应该只与这些 “朋友” 对象进行交互,而避免与其他对象产生不必要的依赖。 比如说,小明(一个对象)有一部手机(成员对象),他用手机(与成员对象交互)打电话给朋友小红(方法参数对象)。在这个场景里,手机和小红就是小明的 “朋友”,小明和这些 “朋友” 通信,符合迪米特法则 。要是小明不通过手机,而是直接去和小红的手机通信,就违反了迪米特法则,因为这引入了不必要的复杂性和依赖关系。

二、深入剖析迪米特法则

(一)法则核心:最少知识原则

        迪米特法则的核心,即最少知识原则,要求对象之间的交互尽可能简单直接。就像在一个公司里,每个员工只专注于自己的本职工作和与直接相关的同事协作,而不是对公司里所有部门和人员的工作都了如指掌。在软件系统中,一个类不应该依赖过多其他类的实现细节,只需要了解与自己直接交互的类的必要信息 。这样,当某个类的内部实现发生变化时,对其他类的影响就会最小化,从而降低了系统的维护成本和出错风险。

        假设我们正在开发一个电商系统,其中有一个订单类 Order 和一个支付类 Payment 。订单类只需要知道支付类提供了支付的方法,而不需要了解支付类内部是如何进行支付验证、与第三方支付平台交互等细节。订单类只和支付类进行必要的通信,调用支付类的支付方法完成支付操作,这就符合最少知识原则。如果订单类深入了解支付类的内部实现,一旦支付类的实现方式发生改变,比如更换了第三方支付平台,订单类也需要进行大量修改,这显然不利于系统的维护和扩展。

(二)“朋友圈” 划定:谁是直接朋友?

        在迪米特法则中,明确 “直接朋友” 的概念至关重要。直接朋友是指那些与当前对象有紧密联系,出现在成员变量、方法参数、方法返回值中的类 。这些类与当前对象的交互是直接且必要的,就像我们生活中的亲密朋友,经常有密切的往来。

        还是以上述电商系统为例,在订单类 Order 中,如果有一个支付对象 Payment 作为成员变量,用于处理订单的支付操作,那么 Payment 类就是 Order 类的直接朋友 。又比如订单类的某个方法接收一个用户类 User 作为参数,用于验证订单所属用户的信息,此时 User 类也是 Order 类的直接朋友 。因为这些类与订单类的交互是直接且必要的,它们之间的耦合关系是合理的。

与之相对的是,局部变量中的类通常不是直接朋友。因为局部变量的作用范围仅限于方法内部,它与当前对象的联系相对松散,就像在社交场合中偶尔认识的人,只是短暂交流,并非真正的 “朋友”。如果在一个类的方法中频繁创建和使用局部变量来与其他类交互,就可能违反迪米特法则,增加类之间不必要的耦合。

(三)广义与狭义:法则的不同视角

        迪米特法则有广义和狭义之分 。狭义的迪米特法则强调类之间通信的直接性,即如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用 。如果其中一个类需要调用另一个类的某个方法,可以通过第三者转发这个调用 。这种方式可以降低类之间的直接耦合,但可能会引入一些中介类,增加系统的复杂性。

        比如在一个社交网络系统中,用户 A 和用户 C 之间没有直接的联系,但用户 A 想要获取用户 C 的一些公开信息。按照狭义的迪米特法则,用户 A 不应该直接与用户 C 交互,而是通过他们共同的好友用户 B 来获取这些信息 。用户 B 在这里就充当了一个中介的角色,转发用户 A 的请求给用户 C,并将结果返回给用户 A。

        广义的迪米特法则则更侧重于类的设计和信息隐藏,涵盖了类的结构设计、信息流量和流向以及信息的影响控制等方面 。它要求在类的划分上,创建有弱耦合的类,每个类都应当尽量降低成员的访问权限,将不必要的信息隐藏在类的内部 。同时,在对其他类的引用上,一个对象对其他对象的引用应当降到最低 。通过这种方式,实现系统的高内聚、低耦合,提高系统的可维护性和可扩展性。

        在设计一个图形绘制系统时,不同类型的图形类(如圆形类 Circle、矩形类 Rectangle 等)应该将自己的绘制逻辑和内部状态封装起来,只对外提供必要的接口方法 。其他类在使用这些图形类时,只需要调用这些接口方法,而不需要了解图形类内部的实现细节 。这样,当需要修改某个图形类的绘制算法时,不会影响到其他使用该图形类的部分,体现了广义迪米特法则的思想。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大雨淅淅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值