当前位置:   article > 正文

设计模式七大原则之迪米特法则_迪米特法则实例

迪米特法则实例

设计模式七大原则之迪米特法则

一、什么是迪米特法则

迪米特法则(Demeter Principle)又叫最少知道原则, 一个类对自己依赖的类知道的越少越好

简单来说, 迪米特法则有两层含义

  • 一个是针对的是依赖其他类的类(以下简称为依赖类), 依赖类只与直接的朋友通信.

朋友关系- 只要两个对象之间有耦合关系, 我们就说这两个对象之间是朋友关系.

直接朋友关系- 耦合关系出现在成员变量、方法参数、方法返回值中的类为直接的朋友关系.

非直接朋友关系- 非直接朋友关系, 常见的就是耦合关系出现在局部变量中.

所以说依赖关系最好不要以局部变量的形式出现在类的内部.

  • 一个是针对的是被依赖的类,被依赖的类尽量将逻辑封装在类的内部. 对外除了提供的public方法, 不对外泄露任何信息.

二、应用案例

案例描述: 有一个学校,下属有各个学院和总部, 现要求打印出学校总部员工ID和学院员工的ID

2.1错误代码演示
2.1.1 类图

2.1.2 代码演示
package com.inconspicuousy.principle.demeter.error;

import lombok.*;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/** 学校总部员工类 */
@Getter
@Setter
@RequiredArgsConstructor
class Employee {
    /** 学校总部员工ID */
    @NonNull private String id;
}

/** 学院员工类 */
@Getter
@Setter
@RequiredArgsConstructor
class CollegeEmployee {
    /** 学院员工ID */
    @NonNull private String id;
}

/** 学院管理类 */
class CollegeManager {
    /** 返回学院所有的员工 */
    public List<CollegeEmployee> findAllEmployee() {
        // 添加10个员工到列表
        return IntStream.rangeClosed(1, 10).boxed()
                .map(i -> new CollegeEmployee("学院ID" + i))
                .collect(Collectors.toList());
    }
}
/** 学校总部管理类 */
class SchoolManager {
    /** 返回学校总部所有的员工 */
    public List<Employee> findAllEmployee() {
        // 添加5个员工到列表
        return IntStream.rangeClosed(1, 5).boxed()
                .map(i -> new Employee("学校总部ID" + i))
                .collect(Collectors.toList());
    }

    /** 打印出所有的员工信息 */
    public void printAllEmployee(CollegeManager collegeManager) {
        System.out.println("=================学院员工=====================");
        // 这里有一个问题就是, 按照案例描述, 我们在设计时, 学校总部应该不需要牵涉到学院的员工, 也就是
        // SchoolManager不应该与CollegeEmployee产生耦合关系
        // 这里在遍历过程中实质上引入了CollegeEmployee局部变量, 出现了非直接朋友关系类, 不符合迪米特法则,
        collegeManager.findAllEmployee().forEach(collegeEmployee -> System.out.println(collegeEmployee.getId()));
        System.out.println("==============学校总部员工==============");
        findAllEmployee().forEach(employee -> System.out.println(employee.getId()));
    }
}

/**
 * 迪米特法则错误案例
 *
 * <p>应用案例: 有一个学校,下属有各个学院和总部, 现要求打印出学校总部员工ID和学院员工的ID</p>
 *
 *  @author peng.yi
 */
public class DemeterErrorExample {
    public static void main(String[] args) {
        SchoolManager schoolManager = new SchoolManager();
        schoolManager.printAllEmployee(new CollegeManager());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
2.1.3 执行结果
=================学院员工=====================
学院ID1
学院ID2
学院ID3
学院ID4
学院ID5
学院ID6
学院ID7
学院ID8
学院ID9
学院ID10
==============学校总部员工==============
学校总部ID1
学校总部ID2
学校总部ID3
学校总部ID4
学校总部ID5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这里主要的错误的原因就在于SchoolManager类中与CollegeEmployee类发生耦合产生了非直接朋友关系, 违背了迪米特法则. 其实优化点就在于只要SchoolManager与CollegeEmployee不发生耦合就行, 而发生耦合的位置就是打印输出学院员工信息, 所以我们将输出学院员工信息的方法提取到CollegeManager类中即可.

2.2 优化后核心代码
/** 学院管理类 */
class CollegeManager {
    /** 返回学院所有的员工 */
    public List<CollegeEmployee> findAllEmployee() {
        // 添加10个员工到列表
        return IntStream.rangeClosed(1, 10).boxed()
                .map(i -> new CollegeEmployee("学院ID" + i))
                .collect(Collectors.toList());
    }

    /** 打印所有的学院员工信息, 将学院员工信息在学院管理类打印, 避免学校管理类与之发生耦合 */
    public void printAllEmployee() {
        findAllEmployee().forEach(collegeEmployee -> System.out.println(collegeEmployee.getId()));
    }
}
/** 学校总部管理类 */
class SchoolManager {
    /** 返回学校总部所有的员工 */
    public List<Employee> findAllEmployee() {
        // 添加5个员工到列表
        return IntStream.rangeClosed(1, 5).boxed()
                .map(i -> new Employee("学校总部ID" + i))
                .collect(Collectors.toList());
    }

    /** 打印出所有的员工信息 */
    public void printAllEmployee(CollegeManager collegeManager) {
        System.out.println("=================学院员工=====================");
        collegeManager.printAllEmployee();
        System.out.println("==============学校总部员工==============");
        findAllEmployee().forEach(employee -> System.out.println(employee.getId()));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

三、迪米特法则注意事项

  • 迪米特法则核心是降低类之间的耦合, 并不是要求完全没有依赖关系.
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/488507
推荐阅读
相关标签
  

闽ICP备14008679号