赞
踩
迪米特法则(Demeter Principle)又叫最少知道原则, 一个类对自己依赖的类知道的越少越好
简单来说, 迪米特法则有两层含义
依赖其他类的类(以下简称为依赖类)
, 依赖类只与直接的朋友
通信.
朋友关系
- 只要两个对象之间有耦合关系, 我们就说这两个对象之间是朋友关系.
直接朋友关系
- 耦合关系出现在成员变量、方法参数、方法返回值中的类为直接的朋友关系.
非直接朋友关系
- 非直接朋友关系, 常见的就是耦合关系出现在局部变量中.
所以说依赖关系最好不要以局部变量的形式出现在类的内部.
被依赖的类
,被依赖的类尽量将逻辑封装在类的内部. 对外除了提供的public方法, 不对外泄露任何信息.案例描述: 有一个学校,下属有各个学院和总部, 现要求打印出学校总部员工ID和学院员工的ID
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()); } }
=================学院员工===================== 学院ID1 学院ID2 学院ID3 学院ID4 学院ID5 学院ID6 学院ID7 学院ID8 学院ID9 学院ID10 ==============学校总部员工============== 学校总部ID1 学校总部ID2 学校总部ID3 学校总部ID4 学校总部ID5
这里主要的错误的原因就在于SchoolManager
类中与CollegeEmployee
类发生耦合产生了非直接朋友关系, 违背了迪米特法则. 其实优化点就在于只要SchoolManager与CollegeEmployee不发生耦合就行, 而发生耦合的位置就是打印输出学院员工信息, 所以我们将输出学院员工信息的方法提取到CollegeManager类中即可.
/** 学院管理类 */ 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())); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。