美文网首页
设计模式之禅(四) -- 迪米特法则

设计模式之禅(四) -- 迪米特法则

作者: OakesYa | 来源:发表于2021-06-08 18:43 被阅读0次

定义

迪米特法则也叫最少知道原则,即一个对象应该对其他对象有最少的了解,一个类对需要耦合的类知道的最少,也即高内聚低耦合。

四层含义

  • 只和朋友交流(类只和必须关联的类去耦合)
  • 朋友之间也是有距离的(耦合类之间减少)
  • 是自己的就是自己的
  • 谨慎使用Serializable接口

只和朋友交流

public class Girl {
}

public class GroupLeader {

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

public class Teacher {

    public void command(GroupLeader groupLeader) {
        List listGirls = new ArrayList();
        //初始化女生
        for (int i = 0; i < 20; i++) {
            listGirls.add(new Girl());
        }
        //告诉体育委员开始执行清查任务
        groupLeader.countGirls(listGirls);
    }
}

public class Client {

    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        //老师发布命令
        teacher.command(new GroupLeader());
    }
}

我们看上面这个例子里面Teacher既跟GroupLeader交互,也跟Gril直接交互。这明显违背了只跟朋友交互的问题。

public class Girl {
}

public class GroupLeader {

    private List<Girl> listGirls;

    //传递全班的女生进来
    public GroupLeader(List<Girl> listGirls) {
        this.listGirls = listGirls;
    }

    //清查女生数量
    public void countGirls() {
        System.out.println("女生数量是:" + listGirls.size());
    }
}

public class Teacher {

    //老师对学生发布命令,清一下女生
    public void command(GroupLeader groupLeader) {
        //告诉体育委员开始执行清洁任务
        groupLeader.countGirls();
    }
}

public class Client {

    public static void main(String[] args) {
        //产生一个女生群体
        List<Girl> listGirls = new ArrayList<>();
        //初始化女生
        for (int i = 0; i < 20; i++) {
            listGirls.add(new Girl());
        }
        Teacher teacher = new Teacher();

        //老师发布命令
        teacher.command(new GroupLeader(listGirls));
    }
}

修改后的类图是



我们发现代码更改后Teacher类只跟GroupLeader沟通,不再需要跟Girl类耦合。

朋友圈也是有距离的

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

    //第二步
    public int second() {
        System.out.println("执行第二个方法...");
        return random.nextInt(100);
    }

    //第三步
    public int third() {
        System.out.println("执行第三个方法...");
        return random.nextInt(100);
    }
}

public class InstallSoftware {

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

public class Client {

    public static void main(String[] args) {
       InstallSoftware invoker = new InstallSoftware();
       invoker.installWizard(new Wizard());
    }
}

我们看上面这一段逻辑就是很简单的一个安装软件的过程,似乎一眼看起来并没有问题,但其实wizard自身的安装逻辑方法很多都暴露给了调用方,如果任意一个安装方法返回类型变化必然会引起调用方变化,实际安装的变化应该隐藏在wizard内部,所以我们修改一下。

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

    //第二步
    private int second() {
        System.out.println("执行第二个方法...");
        return random.nextInt(100);
    }

    //第三步
    private int third() {
        System.out.println("执行第三个方法...");
        return random.nextInt(100);
    }

    public void installWizard( ) {
        int first = first();
        //根据first返回的结果,看是否执行second
        if (first > 50) {
            int second = second();
            //根据second返回的结果,看是否执行third
            if (second > 50) {
                int third = third();
                //根据third返回的结果,看是否执行first
                if (third > 50) {
                    first();
                }
            }
        }
    }
}

public class InstallSoftware {

    public void installWizard(Wizard wizard) {
        wizard.installWizard();
    }
}

public class Client {

    public static void main(String[] args) {
       InstallSoftware invoker = new InstallSoftware();
       invoker.installWizard(new Wizard());
    }
}

我们将wizard的安装步骤方法改成private,并将安装步骤移到wizard中,迪米特法则要求类尽量不要对外公布太多的public方法和非静态的public变量,尽量内敛。

是自己的就是自己的

在实际场景中我们会遇到一个方法放在本类中也可以,放在其他类中也没有错的情况,书中的建议是如果一个方法放在本类中,即不增加类间关系,也对本类不产生负面影响,那就放置在本类中,不过我们组在工作中是通过判读这个方法能力应该由谁来提供,在UML建模时就可以探讨出来放在那里合适

谨慎使用Serializable接口

Serializable接口主要用于远程方法调用中序列化一个对象进行网络传输,如果客户端的对象修改了对象属性的权限,譬如从public修改成private,服务器上没有做相应变化时会序列化失败。

思考与总结

我将迪米特法则简单描述成是你的就是你的,不是你的你不要,就算是你的你也得珍惜,这三句话分别对应了前三个原则,我在实际工作中CR或者编程没有想着说我要以六大原则去审视一下自己的代码,在工作中通过UML模型图以及控制好方法的权限没啥问题就通过了,所以等开闭原则学完之后以六大原则审视一下自己负责的项目,看是否有优化的地方,CR或者编写时是否可以找到一套方法论去更好的校验或评判。

相关文章

  • 设计模式六大原则--迪米特法则(Law of Demeter,

    参考书籍:设计模式之禅 --- 秦小波 迪米特法则(Law of Demeter, LOD)也称最少知识法则( L...

  • 迪米特法则

    个人博客原文:迪米特法则 设计模式六大原则之五:迪米特法则。 简介 姓名:迪米特法则 英文名:Law of Dem...

  • 设计模式之禅(四) -- 迪米特法则

    定义 迪米特法则也叫最少知道原则,即一个对象应该对其他对象有最少的了解,一个类对需要耦合的类知道的最少,也即高内聚...

  • 设计模式之迪米特法则

    设计模式之迪米特法则 迪米特法则(Law of Demeter) 定义:一个类对其它类知道的越少越好 一个对象应该...

  • 《设计模式》——迪米特法则

    定义   其实《设计模式之禅》关于原则的部分,我最喜欢的就是《迪米特法则》没什么特殊原因,前段时间部门培训,让我出...

  • [Code Design] 六大设计原则之`迪米特法则`

    六大设计原则之迪米特法则 定义 迪米特法则(Law of Demeter)又叫作最少知识原则(Least Know...

  • 设计模式之迪米特法则

    相关链接:0. 设计模式之六大原则总结1. 设计模式之单一职责原则2. 设计模式之里式替换原则3. 设计模式之依赖...

  • 设计模式---外观设计模式

    外观模式 标签(空格分隔): 设计模式 在设计模式中有一个法则叫迪米特法则(最少知识原则),它说的是什么呢? 一个...

  • 设计模式 - 迪米特法则

    如果两个类不必彼此之间直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个了类的某一个方...

  • 设计模式 -- 迪米特法则

    表述(降低耦合) 第一表述:一个对象应该对其他对象保持最少了解, 通俗的讲就是一个类对自己依赖的类知道的越少越好,...

网友评论

      本文标题:设计模式之禅(四) -- 迪米特法则

      本文链接:https://www.haomeiwen.com/subject/jnrmsltx.html