• 迪米特法则


    也称为最少知道原则(Least Knowledge Principle 简写LKP)

    迪米特法则是用来干什么的?

    他的初衷是:降低类之间的耦合。

    以我目前的视野,我认为迪米特法则就是一个在类创建方法和属性时需要遵守的法则。

    什么是迪米特法则?

    迪米特法则由三个守则组成:

    守则1:是自己的就是自己的

    如果一个方法放在本类中,即不增加类间关系,也对本类不产生负面影响就放在本类中。

    守则2:一个类只与他的朋友类进行交互。talk only to your immediate friends

    在弄明白这个守则之前,我们需要弄清什么叫做朋友类:

    在遵守守则1的前提下,为类A创建了一个方法,那么该方法Method中的参数必然是某基本类型(包括void类型)的变量,或者是某个类的对象。

    如果是后者即某个类的对象,我们将该类称之为类B,那么类B即为类A的朋友类。

    那么守则2的意思是类A的方法Method只与类B以及类A的属性进行交流,在该方法中不再引入其他第三方类。

    除了方法中的参数的类型可能成为朋友类,属性的类型也是朋友类(基本类型除外)。

    以下给出例子:

    例如,老是想让体育委员确认以下女生人数,我们来看怎么用程序来实现,类图如图:

    image

    Teacher类的commond方法负责发送命令给体育委员,命令他清点女生,其实现过程如下:

    image 

    老师只有一个commond方法,先定义出所有的女生,然后发命令给体育委员,去清点以下女生的数量。体育委员GroupLeader的实现过程如下:

    image

    老师类和体育委员类都对女生类产生了依赖,而且女生类不需要执行任何动作,因此定义一个空类,如图:

    image 

    故事中的三个角色都有了,在定义一个场景来描述这个故事,实现过程如下:

    image

    运行结果:

    image

    体育委员按照老师的要求对女生进行了清点,并得出了数量。我们回过头来思考一下这个程序有什么问题,首先确定Teacher有几个朋友类,他仅有一个朋友类:GroupLeader。为什么Girl不是朋友类呢?Teacher也对他产生了依赖关系啊!朋友类的定义是这样的:出现在成员变量,方法的输入输出中的类称为成员朋友类。迪米特法则告诉我们一个类只和朋友类交流,但是我们刚刚定义的commond方法却与Girl类有了交流,声明了一个List动态数组,也就是与一个陌生的类Girl有了交流,这样就破坏了Teacher的健壮性。方法是类的一个行为,类竟然不知道与其他类产生了依赖关系,这是不允许的,严重违反了迪米特法则。

    可以这样子修改,在类图中去掉Teacher对Girl类的依赖关系,修改后的Teacher类如下:

    image

    修改后的体育委员类:

    image

    修改后的场景类:

    image

    把Teacher中对List的初始化移动到了场景类中,同时在GroupLeader中增加了对Girl的注入,避开了Teacher类对陌生类Girl的访问,降低了系统间的耦合,提高了系统的健壮性。

    注意:一个类只和朋友交流,不与陌生类交流,类与类之间的关系是建立在类间的,而不是方法间,因此一个方法尽量不引入一个类中不存在的对象,当然JDK API提供的类除外。

     守则3:朋友间也是有距离的

    朋友间是有距离的,太远关系逐渐疏远,最终形成陌路;太近就互相刺伤,必须保持一个合适的距离。迪米特法则就是对这个距离的描述,即使是朋友类之间也不能无话不说,无所不知。

    例如,我们在安装软时,经常有一个导向动作,第一步是确认是否安装,第二步是确认License,然后再选择安装目录;这是一个典型的顺序执行动作,具体到程序中就是:调用一个或者多个类,先执行第一个方法,然后是第二个方法,根据返回结果再来看是否调用第三个方法,其类图如下:

    image

    很简单的类图,实现软件安装的过程,其中first方法定义第一步做什么,second方法定义第二步做什么,其实现过程如下:

    imageInstallSoftware类:

    image程序虽然简单,隐藏的问题可不简单,思考一下程序有什么问题。Wizard类把太多的方法暴露给InstallSoftware类,两者的朋友关系太紧密了,耦合关系变得异常牢固。如果要将Wizard类中的first方法返回值的类型由int改为boolean,就需要修改InstallSoftware类,从而把修改变更的风险扩散开来。因此这样的耦合是极度不合适的,我们需要重新对设计进行重构,重构后的类图如下:

    image   在Wizard类方法中增加一个installWizard方法,对安装过程进行封装,同时把原有的三个public方法修改为private方法,如下所示:

    image

    修改后的InstallSoftware类:

    image通过这样的重构后,Wizard类对外只公布了一个public方法,即使要修改first的返回值,影响的也只是Wizard本身,其他类不受影响,这显示了类的高内聚特性。

    注意:迪米特法则要求类“羞涩”一点,尽量不要对外公布太多的public方法和非静态的public变量,尽量内敛,多使用private、protected等访问权限。

  • 相关阅读:
    spring初始化bean时执行某些方法完成特定的初始化操作
    flask与数据库连接相关操作
    解决flask中文乱码的问题
    flask(1)
    First Unique Character in a String (找到一个字符串中第一个不重复的字符)
    Java hashCode() 方法
    Java 类和对象
    Java 一维数组的定义和初始化
    Maven 在运行部署的时候是如何确定推送到 releases 还是 snapshots 仓库的
    Samples for Parallel Programming with the .NET Framework
  • 原文地址:https://www.cnblogs.com/silentjesse/p/3510966.html
Copyright © 2020-2023  润新知