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

64 阅读3分钟

定义

迪米特法则又称为最少知道原则,是指一个类对于其他类来说,知道的越少越好。意义降低类之间的耦合,保持最少关联性,最终实现高内聚低耦合。

模拟案例

模拟学生、老师、校长之间的关系。 老师负责学生的学习情况 校长关心老师所在班级的成绩 如果校长想知道一个班级的平均分和总分,是应该找老师要还是跟每一个学生统计?

违背原则方法

学生

/**
 * @description:学生类
 * @version: 1.0
 * @Author blackcat
 */
public class Student {
​
    /**
     * 学生姓名
     */
    private String name;
​
    /**
     * 考试排名
     */
    private int rank;
​
    /**
     * 考试分数
     */
    private double grade;
​
​
    public Student(String name, int rank, double grade) {
        this.name = name;
        this.rank = rank;
        this.grade = grade;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getRank() {
        return rank;
    }
​
    public void setRank(int rank) {
        this.rank = rank;
    }
​
    public double getGrade() {
        return grade;
    }
​
    public void setGrade(double grade) {
        this.grade = grade;
    }
}
​

老师

/**
 * @description:老师
 * @version: 1.0
 * @Author blackcat
 */
public class Teacher {
​
    /**
     * 老师姓名
     */
    private String name;
​
​
    /**
     * 班级
     */
    private String clazz;
​
​
    /**
     * 班级的学生
     */
    private static List<Student> studentList;
​
​
    public Teacher(String name, String clazz) {
        this.name = name;
        this.clazz = clazz;
    }
​
    static {
        studentList = new ArrayList<>();
        studentList.add(new Student("花花", 10, 589));
        studentList.add(new Student("豆豆", 54, 356));
        studentList.add(new Student("秋雅", 23, 439));
        studentList.add(new Student("皮皮", 2, 665));
        studentList.add(new Student("蛋蛋", 19, 502));
    }
​
    public static List<Student> getStudentList() {
        return studentList;
    }
​
    public String getName() {
        return name;
    }
​
    public String getClazz() {
        return clazz;
    }
}
​

校长

/**
 * @description:校长
 * @version: 1.0
 * @Author blackcat
 */
public class Principal {
​
    private Teacher teacher = new Teacher("丽华", "3年1班");
​
​
​
    /**
     * 查询班级信息,总分数、学生人数、平均值
     * @param clazzId
     * @return
     */
    public Map<String, Object> queryClazzInfo(String clazzId) {
        // 获取班级信息;学生总人数、总分、平均分
        int stuCount = clazzStudentCount();
        double totalScore = clazzTotalScore();
        double averageScore = clazzAverageScore();
​
        // 组装对象,实际业务开发会有对应的类
        Map<String, Object> mapObj = new HashMap<>();
        mapObj.put("班级", teacher.getClazz());
        mapObj.put("老师", teacher.getName());
        mapObj.put("学生人数", stuCount);
        mapObj.put("班级总分数", totalScore);
        mapObj.put("班级平均分", averageScore);
        return mapObj;
    }
​
​
​
    /**
     *  总分
     * @return
     */
    public double clazzTotalScore() {
        double totalScore = 0;
        for (Student stu : Teacher.getStudentList()) {
            totalScore += stu.getGrade();
        }
        return totalScore;
    }
​
​
​
    /**
     * 平均分
     * @return
     */
    public double clazzAverageScore(){
        double totalScore = 0;
        for (Student stu : Teacher.getStudentList()) {
            totalScore += stu.getGrade();
        }
        return totalScore / Teacher.getStudentList().size();
    }
​
    /**
     * 班级人数
     * @return
     */
    public int clazzStudentCount(){
        return Teacher.getStudentList().size();
    }
}
​

校长类关联了老师和学生,如果所有班级的学生都让校长维护,代码就会变得非常臃肿,不易拓展和维护。

迪米特法则改善代码

校长关心老师,老师负责学生,把老师提供查询相关学生的服务

学生类不变

/**
 * @description:学生类
 * @version: 1.0
 * @Author blackcat
 */
public class Student {
​
    /**
     * 学生姓名
     */
    private String name;
​
    /**
     * 考试排名
     */
    private int rank;
​
    /**
     * 考试分数
     */
    private double grade;
​
​
    public Student(String name, int rank, double grade) {
        this.name = name;
        this.rank = rank;
        this.grade = grade;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getRank() {
        return rank;
    }
​
    public void setRank(int rank) {
        this.rank = rank;
    }
​
    public double getGrade() {
        return grade;
    }
​
    public void setGrade(double grade) {
        this.grade = grade;
    }
}
​

老师

把计算总分、平均分、人数的方法放入老师类,校长直接调用老师类的方法。 校长-->老师-->学生

/**
 * @description:老师
 * @version: 1.0
 * @Author blackcat
 */
public class Teacher {
​
    /**
     * 老师姓名
     */
    private String name;
​
​
    /**
     * 班级
     */
    private String clazz;
​
​
    /**
     * 班级的学生
     */
    private static List<Student> studentList;
​
​
    public Teacher(String name, String clazz) {
        this.name = name;
        this.clazz = clazz;
    }
​
    static {
        studentList = new ArrayList<>();
        studentList.add(new Student("花花", 10, 589));
        studentList.add(new Student("豆豆", 54, 356));
        studentList.add(new Student("秋雅", 23, 439));
        studentList.add(new Student("皮皮", 2, 665));
        studentList.add(new Student("蛋蛋", 19, 502));
    }
​
    public static List<Student> getStudentList() {
        return studentList;
    }
​
    public String getName() {
        return name;
    }
​
    public String getClazz() {
        return clazz;
    }
​
​
    /**
     *  总分
     * @return
     */
    public double clazzTotalScore() {
        double totalScore = 0;
        for (Student stu : studentList) {
            totalScore += stu.getGrade();
        }
        return totalScore;
    }
​
​
​
    /**
     * 平均分
     * @return
     */
    public double clazzAverageScore(){
        double totalScore = 0;
        for (Student stu : studentList) {
            totalScore += stu.getGrade();
        }
        return totalScore / Teacher.getStudentList().size();
    }
​
    /**
     * 班级人数
     * @return
     */
    public int clazzStudentCount(){
        return studentList.size();
    }
}
​

校长

/**
 * @description:校长
 * @version: 1.0
 * @Author blackcat
 */
public class Principal {
​
    private Teacher teacher = new Teacher("丽华", "3年1班");
​
​
​
    /**
     * 查询班级信息,总分数、学生人数、平均值
     * @param clazzId
     * @return
     */
    public Map<String, Object> queryClazzInfo(String clazzId) {
        // 获取班级信息;学生总人数、总分、平均分
        int stuCount = teacher.clazzStudentCount();
        double totalScore = teacher.clazzTotalScore();
        double averageScore = teacher.clazzAverageScore();
​
        // 组装对象,实际业务开发会有对应的类
        Map<String, Object> mapObj = new HashMap<>();
        mapObj.put("班级", teacher.getClazz());
        mapObj.put("老师", teacher.getName());
        mapObj.put("学生人数", stuCount);
        mapObj.put("班级总分数", totalScore);
        mapObj.put("班级平均分", averageScore);
        return mapObj;
    }
​
​
​
​
}
​

测试

/**
 * @description:
 * @version: 1.0
 * @Author blackcat
 */
@Slf4j
public class ApiTest {
​
​
    @Test
    public void test_principal() {
        Principal principal = new Principal();
        Map<String, Object> map = principal.queryClazzInfo("3年1班");
        log.info("查询结果:{}",map.toString());
    }
}
​

总结

考虑类与类之间的交互,正确使用public 修饰方法,松耦合