迪米特法则讲解

迪米特法则讲解

迪米特法则,还有叫最少知道原则的,我们现在再来看一下定义,一个对象应该对其他对象保持最少知道的了解,

又叫最少知道原则,尽量降低类与类之间的耦合,那迪米特主要强调的是降低耦合,优点也自然是降低类之间的耦合,

那从代码层面呢,最少知道,也就是该知道的知道,不该知道的不知道,尽量不要对外公开太多的public方法,

和非静态的public变量,尽量内敛,多使用private,包权限,还有protected等访问权限,那迪米特原则的核心观念,

是类之间的解耦,那解耦是有一定程度的,我们尽量做到弱耦合,只有耦合越低,类的复用率还可能提高,减少了每个

类之间不必要的依赖,从而降低耦合的一个关系,凡是要有个度,之前我也有强调,你如果过分的使用迪米特原则,

会产生大量的中介类,导致系统变复杂,为维护带来了难度,所以我们在使用迪米特的原则,要反复权衡,要做到

结构清晰,需要做到低耦合,高内聚,那平时我们在做编码的时候,经常碰到一种场景,也就是说一个方法,我放到A类也行,

放到B类也行,那这种情况我们该怎么做呢,我们可以坚持一个原则,如果一个方法放在一个本类中,既不增加类之间的关系,

也对本类不产生影响,那就可以放在本类中,那一会我们在coding的时候,引着大家来看UML类图

迪米特法则讲解

迪米特原则我们主要强调什么,强调只和朋友交流,不和陌生人说话,在这里面我们就要讲一个概念,在迪米特原则中,

朋友出现在成员变量,方法的入参和出参中,这里面的类称之为朋友类,而出现在方法体内部的类,是不属于朋友类的,

不和陌生人说话,就是不该了解的类我们不需要
那迪米特法则也叫最少知道原则,那最少知道原则就比较好理解了,我不应该知道的我就不应该知道,那这句话就是一句

废话,简单的理解,他的表现形式呢,是我对外部引入的类,越少越好,但是目的和结果,是一致的,要完成这个类和方法的一个

原则,强调的是只和直接的朋友交流,那么每个类和其他对象,肯定是有耦合关系的,那朋友关系组合聚合,依赖等等这些关系,

都可以称之为朋友关系,迪米特是为了降低类之间的耦合,尽量减少对其他类的依赖,这样才能使系统得到独立,相互之间不

存在,减少依赖关系,提高内聚,那我们新建一个包,那我现在有一个业务场景,比如说,大老板说你给我查一下,到现在为止

线上有多少个课程,那这里面关系到几个类

迪米特法则讲解

迪米特法则讲解

迪米特法则讲解

Test应用的client,主要是看这三个,这个排版是IDEA自动排版的,根据不同的元素它会自动排版,

那这个排版就比较清晰,Course不应该是由Boss来创建的,而应该是由TeamLeader,指向Course的箭头

应该是由TeamLeader来指向他,这个就是从UML角度来分析的,迪米特法则,Test是应用层,把它认为是客户端,

他来调整体的服务,他来创建Boss和TeamLeader,这个先忽略,主要是看他们三的一个关系,那我们现在来修改一下实现
package com.learn.design.principle.demeter;


/**
 * 首先Boss这里面有一个方法
 * 
 * 有很多人觉得这么写也没有什么问题
 * 我们一起来分析一下
 * 看他到底存不存在一些可以改进的点
 * 那我们看一下Boss的这个方法
 * 之前我们也强调过
 * 迪米特法则主要讲的是只和直接的朋友交流
 * 例如Boss
 * TeamLeader他作为一个入参
 * 它是直接的朋友
 * 朋友的定义
 * 就是出现在类成员变量里
 * 比如这里有一个成员变量
 * 还有方法的入参
 * TeamLeader
 * 还有返回值输出
 * 也就是说方法的输入和输出
 * 也都是直接的朋友
 * 不过我们现在这里是一个void
 * 而方法体内部的类
 * 不算朋友
 * 例如这个Course这个类
 * 他并不算是Boss的朋友
 * 所以Course不是Boss的朋友
 * Boss直接给TeamLeader下指令
 * TeamLeader查完之后
 * 直接把结果给Boss就可以了
 * Boss不需要关注
 * 他和TeamLeader是直接的关系
 * 不应该和陌生的Course类发生交流
 * 那目前的这种写法呢
 * 就违背了迪米特法则
 * 如果Boss TeamLeader Course并不在同一个包下
 * 我们就会发现在这个类里面
 * import Course这个类
 * import Course这个类并没有出现在直接朋友的这个位置
 * 例如成员变量方法的入参
 * 还有返回值
 * 但是我们也要import导入进来
 * 那这个其实在某种情况下一种判断的方式
 * 那我们看一下类图
 * 我们看完类图
 * 就会比较清晰
 * 同时我们看一下他们之间的变化
 * 包括我们改进之后的
 * 
 * 
 * 
 * @author Leon.Sun
 *
 */
public class Boss {

	/**
	 * Boss查课程的一个数量
	 * 方法名就叫这个了
	 * 这里面传入一个TeamLeader
	 * 给TeamLeader下指令
	 * 让他查课程的数量
	 * 那现在Boss向TeamLeader下指令
	 * 首先初始化一下课程
	 * 
	 * 这里面已经不需要再知道和了解Course类了
	 * 而把这个移到TeamLeader里面
	 * 
	 * 下指令
	 * 给TeamLeader下指令
	 * TeamLeader直接查
	 * Boss不需要了解Course这些类
	 * 然后TeamLeader去和Course类发生接触
	 * 他来查具体的数量
	 * 
	 * 
	 * 
	 * @param teamLeader
	 */
    public void commandCheckNumber(TeamLeader teamLeader){
    	/**
    	 * 这里调用checkNumberOfCourses方法
    	 * 把集合传进来
    	 * 
    	 * 然后Boss这里边参数也不用传了
    	 * 
    	 */
        teamLeader.checkNumberOfCourses();
    }

}
package com.learn.design.principle.demeter;

/**
 * 
 * @author Leon.Sun
 *
 */
public class Course {
}
package com.learn.design.principle.demeter;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * @author Leon.Sun
 *
 */
public class TeamLeader {
	/**
	 * 这里直接把集合课程传进来
	 * 
	 * 这个时候入参就可以干掉了
	 * 
	 */
    public void checkNumberOfCourses(){
    	/**
    	 * 赋值new一个ArrayList
    	 * 导一下包
    	 */
        List<Course> courseList = new ArrayList<Course>();
        /**
         * 那现在开始查数
         * 这里面把它初始化
         * 一个一个查
         * 假设这里面用一个比较笨的方法
         * 下一页下一页的往下查
         * 写一个SQL直接从数据库中查
         * 所以我们模拟一下一页一页的查数
         * 那小时候我们也听过
         * 数鸭子的儿歌
         * 我们采用和数鸭子一样的方式
         * 来数课程
         * 假设一共20个
         * 
         * 
         */
        for(int i = 0 ;i < 20;i++){
        	/**
        	 * 直接往里面add一个Course
        	 * Course对象放在这里
        	 * 
        	 */
            courseList.add(new Course());
        }
        /**
         * 直接输出
         * 
         */
        System.out.println("在线课程的数量是:"+courseList.size());
    }

}
package com.learn.design.principle.demeter;

/**
 * 这里面的逻辑也非常的简单
 * 
 * Course类不变
 * 我们回到Test里边
 * 这个写法也没有变化
 * 结果是一样的
 * 我们遵循这个原则之后呢
 * 在某些业务场景下
 * 应用层代码是不需要变化的
 * 当然需要复杂的场景也是需要变化的
 * 目前我们从Test里面我们看不出变化
 * 那我们来看一下UML
 * 这里面就很清晰了
 * 
 * @author Leon.Sun
 *
 */
public class Test {
    public static void main(String[] args) {
    	/**
    	 * 首先我们new一个Boss
    	 * 
    	 */
        Boss boss = new Boss();
        /**
         * 然后new一个TeamLeader
         * 
         */
        TeamLeader teamLeader = new TeamLeader();
        /**
         * 这个时候我们 commandCheckNumber
         * 把teamLeader传进来
         * 给TeamLeader下指令
         * 查一下数量
         * 
         */
        boss.commandCheckNumber(teamLeader);

    }
}

迪米特法则讲解

Course是由TeamLeade来生成的,Course不再和Boss发生接触,Boss也不需要知道Course,改造后通过类图,

就非常明显了,对于我们的大老板给TeamLeader下指令之后,你查完告诉我结果就可以了,不要让我关心那么多细节,

那迪米特法则理解起来也相当容易,最重要的是我们要分清楚哪些类是直接的朋友,哪些类不是朋友,只要能区分这个,

那我们在遵循迪米特法则进行开发的时候,也就游刃有余了,希望通过学习迪米特法则,在我们日常的工作和学习中呢,

都可以适当的利用起来