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

定义

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

四层含义

  • 只和朋友交流(类只和必须关联的类去耦合)
  • 朋友之间也是有距离的(耦合类之间减少)
  • 是自己的就是自己的
  • 谨慎使用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或者编写时是否可以找到一套方法论去更好的校验或评判。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容