精华内容
下载资源
问答
  • 一、迪米特法则的定义 迪米特法则,也称为最少知识原则,虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,被耦合或调用的类的...

    目录

    一、迪米特法则的定义

    二、迪米特法则的含义

    三、总结


    一、迪米特法则的定义

    迪米特法则,也称为最少知识原则,虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,被耦合或调用的类的内部是如何复杂都和我没关系,我就知道你提供的这么多public方法,我就调用这么多,其他的我一概不关心。

    二、迪米特法则的含义

    迪米特法则对类的低耦合提出了明确的规定,其包含以下几层含义。

    (一)、只和朋友交流

    迪米特法则,要求只与直接朋友通信。什么叫直接朋友?每个对象都必然会与其他对象有耦合关系,两个对象之间的耦合就成为朋友关系,这种关系的类型有很多,例如组合、聚合、依赖等。下面我们举例说明如何才能做到只与直接朋友进行交流。

    举例:老师让体育委员确认一下全班女生是否都到齐?类图如下图所示:

     其实现过程如下代码:

    老师类:

    public class Teacher {
        //老师发出命令,清点一下女生人数
        public void command(GroupLeader groupLeader) {
            List<Girl> girls = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                girls.add(new Girl());
            }
            //告诉体育委员开始执行清查任务
            groupLeader.countGirls(girls);
        }
    }
    

    老师只有一个方法command,先定义出所有的女生,然后发布命令给体育委员,去清点女生的人数。

    体育委员GroupLeader的代码如下:

    public class GroupLeader {
        public void countGirls(List<Girl> girlList) {
            System.out.println("女生数量: " + girlList.size());
        }
    }

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

    public class Girl {
    }

    再定义一个场景类:

    public class Client {
        public static void main(String[] args) {
            Teacher teacher = new Teacher();
            teacher.command(new GroupLeader());
        }
    }

    运行结果如下:

    女生数量: 10

    体育委员按照老师的要求对女生进行了清点,并得出了数量。我们回过头来思考一下这个程序有什么问题,首先确定Teacher类有几个朋友类,它仅有一个朋友类-------GroupLeader,为什么Girl不是朋友类呢?Teacher对Girl类产生了依赖啊,朋友类的定义是这样的:出现在成员变量、方法的输入参数、输出参数中的类成为成员朋友类。而Gril这个类是出现在command方法内部的,因此不属于Teacher的直接朋友。

    迪米特法则告诉我们一个类只与朋友类交流,但是我们刚刚定义的command方法却与Girl类有了交流,声明了List<Girl>动态集合,这样就破坏了Teacher的健壮性。

    问题已经发现,我们修改一下程序,将类图稍作调整,如下图所示:

     修改后的老师类:

    public class Teacher {
        //老师发出命令,清点一下女生人数
        public void command(GroupLeader groupLeader) {
            //告诉体育委员开始执行清查任务
            groupLeader.countGirls();
        }
    }

    修改后的GroupLeader体育委员类:

    public class GroupLeader {
        private List<Girl> girls;
    
        public GroupLeader(List<Girl> girls) {
            this.girls = girls;
        }
    
        public void countGirls() {
            System.out.println("女生数量: " + girls.size());
        }
    }

    在GroupLeader类中定义了一个构造函数,通过构造函数传递了依赖关系。同时,对场景类也进行了一些调整:

    public class Client {
        public static void main(String[] args) {
            List<Girl> girls = new ArrayList<>();
            //初始化女生信息
            for (int i = 0; i < 10; i++) {
                girls.add(new Girl());
            }
            ;
            Teacher teacher = new Teacher();
            //老师发布命令
            teacher.command(new GroupLeader(girls));
        }
    }

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

    (二)、朋友间也是有距离的

    人和人之间是有距离的,太远关系逐渐疏远,最终形同陌路;太近就相互刺伤。迪米特法则就是对这个距离进行描述,即使是朋友类之间也不能无话不说,无所不知。

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

    实现过程如下:

    public class Wizard {
    
        private Random random = new Random(System.currentTimeMillis());
    
        /**
         * 第一步
         *
         * @return
         */
        public int first() {
            System.out.println("执行第一个方法");
            return random.nextInt(100);
        }
    
        /**
         * 第二步
         *
         * @return
         */
        public int second() {
            System.out.println("执行第二个方法");
            return random.nextInt(100);
        }
    
        /**
         * 第三步
         *
         * @return
         */
        public int third() {
            System.out.println("执行第三个方法");
            return random.nextInt(100);
        }
    
    }
    

     在Wizard类中分别定义了三个步骤方法,每个步骤中都有相关的业务逻辑完成指定的任务,我们使用一个随机函数来代替业务执行的返回值。

    InstallSoftware类的代码如下:

    public class InstallSoftware {
        public void install(Wizard wizard) {
            int first = wizard.first();
            //根据first的返回结果,看是否需要执行second
            if (first > 50) {
                int second = wizard.second();
                if (second > 50) {
                    int third = wizard.third();
                    if (third > 50) {
                        wizard.first();
                    }
                }
            }
        }
    }

    根据每个方法执行的结果决定是否继续执行下一个方法,模拟人工的选择操作。场景类如下:

    public class Client {
        public static void main(String[] args) {
            InstallSoftware installSoftware = new InstallSoftware();
            installSoftware.install(new Wizard());
        }
    }

    以上程序很简单,运行结果和随机数有关,每次执行的结果都不相同,需要读者自己运行并查看结果。程序虽然简单,但隐藏的问题可不简单,思考一下程序有什么问题?

    Wizard类把太多的方法暴露给InstallSoftware类,两者的朋友关系太亲密了,耦合关系变得异常牢固。如果要将Wizard类中的first方法返回值的类型由int修改为boolean,就需要修改InstallSoftware类,从而把修改变更的风险扩散开了。因此,这种耦合是不合适的,我们需要对设计进行重构,重构后的类图如下:

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

    public class Wizard {
    
        private Random random = new Random(System.currentTimeMillis());
    
        /**
         * 第一步
         *
         * @return
         */
        private int first() {
            System.out.println("执行第一个方法");
            return random.nextInt(100);
        }
    
        /**
         * 第二步
         *
         * @return
         */
        private int second() {
            System.out.println("执行第二个方法");
            return random.nextInt(100);
        }
    
        /**
         * 第三步
         *
         * @return
         */
        private int third() {
            System.out.println("执行第三个方法");
            return random.nextInt(100);
        }
    
        public void installWizard() {
            int first = this.first();
            //根据first的返回结果,看是否需要执行second
            if (first > 50) {
                int second = this.second();
                if (second > 50) {
                    int third = this.third();
                    if (third > 50) {
                        this.first();
                    }
                }
            }
        }
    
    }

    讲啊三个步骤的访问权限修改为private,同时把InstallSoftware中的方法installWizard()移动到了Wizard类中。通过这样的重构后,Wizard类就只对外公布了一个public方法,即使要修改first方法的返回值,影响的也仅仅是Wizard本身,其他类不受影响,这显示了类的高内聚特性。

    修改后的InstallSoftware代码如下:

    public class InstallSoftware {
        public void install(Wizard wizard) {
            wizard.installWizard();
        }
    }
    

     场景类没有任何改变,通过进行重构,类间的耦合关系变弱了,结构也清晰了,变更引起的风险也变小了。

    一个类公开的public属性或者方法越多,修改时涉及的面就越大,变更引起的风险扩散也就越大。因此,为了保持朋友间的距离,在设计时需要反复衡量:是否还可以再减少public属性和方法,是否可以修改为private、package-private、protected等访问权限,是否可以加上final关键字等。

    (三)、是自己的就是自己的

    在实际应用中经常会出现这样一个方法:放在本类中也可以,放在其他类也没有错,那怎么去衡量呢?可以检查这样一个原则:如果一个方法放在本类中,既不增加类间关系,也对本类不产生负面影响,那就放置在本类中。

    三、总结

    迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用率才可以提高。其要求的结果就是产生了大量的中转或跳转类,导致系统的复杂性提高,同时也为维护带来了难度。读者在采用迪米特法则的时候需要反复权衡,既做到让结构清晰,又做到高内聚低耦合。

    参考:<<设计模式之禅>>

    展开全文
  • 迪米特法则(Law of Demeter, LoD):一个软件实体应当尽可能少地与其他实体...迪米特法则还有几种定义形式,包括:不要和“陌生人”说话、只与你的直接朋友通信等,在迪米特法则中,对于一个对象,其朋友包括以下几...

            迪米特法则(Law of Demeter, LoD):一个软件实体应当尽可能少地与其他实体发生相互作用。

            如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。

    迪米特法则还有几种定义形式,包括:不要和“陌生人”说话、只与你的直接朋友通信等,在迪米特法则中,对于一个对象,其朋友包括以下几类:

    • 当前对象本身(this);

    • 以参数形式传入到当前对象方法中的对象;

    • 当前对象的成员对象;

    • 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;

    • 当前对象所创建的对象。

             任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”,否则就是“陌生人”。在应用迪米特法则时,一个对象只能与直接朋友发生交互,不要与“陌生人”发生直接交互,这样做可以降低系统的耦合度,一个对象的改变不会给太多其他对象带来影响。

             迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。

            在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限;在类的设计上,只要有可能,一个类型应当设计成不变类;在对其他类的引用上,一个对象对其他对象的引用应当降到最低。

    展开全文
  • 设计原则_迪米特法则

    2018-09-04 00:23:11
    迪米特法则(Law of Demeter ,LoD)也称为最少知识原则(Least Knowlege Principle,LKP),虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解。 二、优势 强调类间解耦,增强程序的复用性...

    一、理解
    迪米特法则(Law of Demeter ,LoD)也称为最少知识原则(Least Knowlege Principle,LKP),虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解。
    二、优势
    强调类间解耦,增强程序的复用性。
    三、劣势
    迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合,类的复用率才可以提高,其要求的结果就需要大量的转换类,导致系统的复杂性提高。
    四、应用
    在实际项目中适度考虑这个原则,需要解耦但是解耦是有限度的。

    展开全文
  • 迪米特法则,又作最少知道原则,着眼于降低类之间的耦合。
    定义:一个软件实体应当尽可能少地与其它实体发生交互作用。
    
    问题:类与类之间的关系越密切,耦合度就越大,当其中一个类发生改变时,就会影响到另一个类的使用
    方案:尽量降低类与类之间的耦合。
    
    举个栗子:讲述一个打印公司成员ID的故事。。。
    情况描述:总公司管理者需要打印出所有成员的ID,包括总公司成员名单和分公司成员ID。
    
    违反迪米特法则的实现方式如下:
    
    1. 新建一个总公司成员类Employee,包含一个员工ID。代码如下:
       
    
    2. 新建一个分公司成员类SubEmployee,也包含一个员工ID。代码如下:
       
    
    3. 新建一个分公司管理者类SubCompanyManager,包含一个获得分公司所有成员的ID的方法,代码如下:
       
    
    4. 新建一个总公司管理者类CompanyManager,包含一个获得总公司所有成员的ID的方法和一个打印所有成员ID的方法。代码如下:
       
    
    5. 在类LODFragment中使用类CompanyManager的对象来实现打印所有成员ID的效果。代码如下:
       
    
    6. 运行后的效果,如下:
       
    
    从上述实现方式可以看出,设计的主要问题是在类CompanyManager中,它与分公司成员Subemployee发生了直接的关系,从逻辑上讲总公司只需要与分公司耦合就行了,与分公司的成员没有任何关系,上述的做法显然增加了不必要也不恰当的耦合,根据迪米特法则,应该要避免类中出现这样非直接朋友关系的耦合。
    
    修改方案:分公司管理者与分公司成员是直接朋友关系,所以我们将分公司所有成员ID的打印工作直接交给分公司管理者类来做,总公司直接调用打印就可以了,从而避免了与分公司成员发生耦合。
    
    遵守迪米特法则的实现方式如下:
    
    1. 在类SubCompanyManager中增加一个打印分公司所有成员ID的方法。代码如下:
       
    
    2. 修改类CompanyManager中打印所有成员ID的方法,使用分公司管理者的对象调用分公司所有成员ID的打印方法。代码如下:
       
    
    3. 类LODFragment不需要做更改,直接运行,效果如下:
       
    
       综上所述,迪米特法则的初衷在于降低类之间的耦合。每个类都应尽量少地依赖其他类,因为这样才很容易使得系统的功能模块独立,非朋友关系之间不存在依赖关系。设计模式中的门面模式和中介模式都是迪米特法则应用的例子。
    
    原则:高内聚,低耦合。
    注意:可以直接相互作用的包括
         1. 当前对象本身,this;
         2. 以参数形式传入到当前对象方法中的对象;
         3. 当前对象的成员对象;
         4. 如果当前对象的成员对象是一个集合,那么集合中的元素也可以直接访问;
         5. 当前对象创建的对象。
    
         如果其他对象有相互耦合的情况,尽量采用第三者(友元类)来降低耦合。
    
    优点:有利于软件功能的扩展和维护
    缺点:不宜过分使用迪米特法则,不然会产生大量的中介和传递类,导致系统复杂度变大。
    
    所以在采用迪米特法则时要反复权衡,既要做到结构清晰,又要做到高内聚低耦合。
    展开全文
  • 1 迪米特法则概述 迪米特法则来自于1987年美国东北大学(Northeastern University)一个名为“Demeter”的研究项 目。迪米特法则又称为最少知识原则(LeastKnowledge Principle, LKP),其定义如下: 迪米特法则:每...
  • 前面 本博主说写设计模式模块的内容皆来自《设计模式之禅第二版》,有兴趣的朋友可以去看原创作者的书籍,我写这是为了本人方便或者其它朋友能够单独的看到想看的设计模式。原著写得很好,强烈建议观看原书。...
  • 迪米特法则 迪米特法则,又称为最少知道原则,意思是说:一个对象应该对其他的对象有最少的了解,也就是说,一个类应该与自己需要耦合或者调用的类知道的最少,我不管你内部的实现是负责或者简单,高效或者冗余,那...
  • 迪米特法则来自于1987年美国东北大学(Northeastern University)一个名为“Demeter”的研究项目。迪米特法则又称为最少知识原则(LeastKnowledge Principle, LKP),其定义如下: 迪米特法则(Law of Demeter, ...
  • 迪米特法则最初是用来作为面向对象的系统设计的一种法则,于1987年秋天由Lan Holland美国东北大学为一个叫做迪米特的项目设计提出。 通俗的将,迪米特法则可以叫做:“不要和陌生人说话”! 2、迪米特法则应用...
  • 迪米特法则(Law of Demeter, LoD) ...迪米特法则还有几种定义形式,包括:不要和“陌生人”说话、只与你的直接朋友通信等,在迪米特法则中,对于一个对象,其朋友包括以下几类: 当前对象本身(this) 以参
  • 面向对象设计原则之迪米特法则 2017年10月12日 09:43:03 阅读数:64 迪米特法则来自于1987年美国东北大学(Northeastern University)一个名为“Demeter”的研究项目。迪米特法则又称为最少知识原则...
  • 迪米特法则 开闭原则 迪米特法则定义 一个对象应该对其他对象有最少的了解。 通俗地讲, 一个类应该对自己需要耦合或调用的类知道得最少, 你(被耦合或调用的类) 的内部是如何复杂都和我没关系, 那是你的事情...
  • 迪米特法则

    2021-06-18 19:49:20
    一. 什么是迪米特法则 迪米特法则(Law of Demeter )又叫做最少知识原则,也就是说,一个对象应当对其他对象尽可能...因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为
  • 迪米特法则(Law of Demeter, LoD)是1987年秋天由lan holland美国东北大学一个叫做迪米特的项目设计提出的,它要求一个对象应该对其他对象有最少的了解,所以迪米特法则又叫做最少知识原则(Least Knowledge ...
  • 设计模式——迪米特法则

    热门讨论 2021-05-30 15:29:04
    原则 又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人...迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很.
  • 文章目录系列文章目录前言一、迪米特法则定义二、使用场景总结 前言 一个新人刚入编程这一行的时候,可能正式参加到一个项目之前跟着书本或者教学视屏写了一些五子棋、贪吃蛇等等的小程序。 参加工作之后,...
  • 迪米特法则
  • 迪米特法则应用下的模式

    热门讨论 2019-11-26 20:10:19
    学习代码的时候,我尽可能的去朝着高内聚低耦合的目标去写,然后就出现了一些疑惑,与大家分享。 啥是迪米特法则?     迪米特法则的初衷在于降低类之间的耦合。...因此,应用迪米特法则有可能造...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,557
精华内容 4,622
关键字:

在系统设计中应用迪米特法则