java设计模式4,不要和陌生人说话
Posted 哪 吒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java设计模式4,不要和陌生人说话相关的知识,希望对你有一定的参考价值。
目录
一、迪米特法则
迪米特法则(Law of Demeter)又叫作最少知道原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。
1、目的
降低类与类之间的耦合度
2、定义
迪米特法则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好,对于依赖的类不管有多复杂,都尽量将逻辑封装在类的内部,对外除了提供public方法,不泄漏任何信息。
更简单的说法:只与直接朋友通信。
直接朋友:每个对象都会与其它对象有耦合关系,耦合的方式有很多,依赖、关联、组合、聚合等。我们称出现在成员变量,方法参数,方法返回值中的类称为直接朋友,而出现在局部变量中的类不能称为直接朋友,也就是说,陌生的类不要以局部变量的形式出现在类的内部。
3、注意事项和细节
- 类的结构设计上,尽量降低类成员的访问权限;
- 在类的设计上,优先考虑将一个类设计成不变类;
- 在类的引用上,将引起其他类的次数降到最低;
- 不暴露类的属性成员,而应该提供相应的访问器(getter、setter);
- 谨慎使用序列化(serializable)功能;
过分的使用迪米特原则,会产生大量这样的中介和传递类,类之间需要通信就通过第三方转发的方式,就会造成系统的不同模块之间的通信效率降低、使系统的不同模块之间不容易协调等缺点,同时大大增加了系统的复杂度。所以在釆用迪米特法则时需要反复权衡,确保高内聚和低耦合的同时,保证系统的结构清晰。
二、模拟场景
通过模拟开发部经理、项目经理、员工之间的关系的例子来说明迪米特法则。
- 部门经理需要负责开发部各项目的运营情况;
- 项目经理需要负责一个项目的立项、开发、测试、运维、结算;
- 员工负责一个项目中某个模块的设计、开发、测试;
三、违背原则方案
1、程序员类
员工负责一个项目中某个模块的设计、开发、测试;有姓名、项目、模块、进度、计划完成时间属性。
package com.guor.beanutil.principle.dimit;
import lombok.Data;
@Data
public class Programmer
// 姓名
private String name;
// 项目
private String project;
// 模块
private String module;
// 进度
private String schedule;
// 计划完成时间
private String completePlanTime;
public Programmer(String name, String project, String module, String schedule, String completePlanTime)
this.name = name;
this.project = project;
this.module = module;
this.schedule = schedule;
this.completePlanTime = completePlanTime;
2、项目经理类
在项目经理类中初始化了项目人员信息,同时提供了简单的接口。
package com.guor.beanutil.principle.dimit;
import java.util.ArrayList;
import java.util.List;
public class ProjectManager
// 姓名
private String name;
// 项目
private String project;
// 进度
private String schedule;
// 计划完成时间
private String completePlanTime;
// 项目开发人员
private static List<Programmer> programmerList;
static
programmerList = new ArrayList<>();
programmerList.add(new Programmer("哪吒","哪吒闹海","技术选型,框架搭建","50%","2022-08-31"));
programmerList.add(new Programmer("妲己","哪吒闹海","前端","30%","2022-08-31"));
programmerList.add(new Programmer("敖丙","哪吒闹海","权限项目","20%","2022-08-31"));
programmerList.add(new Programmer("申公豹","哪吒闹海","管理模块","20%","2022-08-31"));
programmerList.add(new Programmer("二郎神","哪吒闹海","数据迁移","10%","2022-08-31"));
public static List<Programmer> getProgrammerList()
return programmerList;
3、开发部经理类
可以获取项目开发人员信息、开发进度、预计交付时间等。
类中通过Stream对代码进行了简化,我觉得Stream是java8新特性中最好用,也是最简洁的,有兴趣的可以体验一下【Java8 新特性 5】Java 8 stream的详细用法
package com.guor.beanutil.principle.dimit;
import java.util.*;
import java.util.stream.Collectors;
public class DepartmentManager
/**
* 获取项目信息
*/
public static Map<String, Object> getProjectInfo()
Map<String, Object> map = new HashMap<>();
String project = ProjectManager.getProgrammerList().get(0).getProject();
Double schedule = getSchedule3();
Date completePlanTime = getCompletePlanTime2();
map.put("项目",project);
map.put("项目进度",schedule);
map.put("预计完成时间",completePlanTime);
return map;
/**
* 项目列表
*/
public static List<String> getProjects()
List<String> list = new ArrayList<>();
List<Programmer> programmerList = ProjectManager.getProgrammerList();
for (Programmer programmer : programmerList)
String project = programmer.getProject();
list.add(project);
return list;
/**
* 获取项目进度
* 写法1
*/
public static double getSchedule1()
List<Programmer> programmerList = ProjectManager.getProgrammerList();
double sum = 0;
for (Programmer programmer : programmerList)
double schedule = programmer.getSchedule();
sum += schedule;
double avg = sum/programmerList.size();
return avg;
/**
* 获取项目进度
* 写法2
*/
public static Double getSchedule2()
List<Programmer> programmerList = ProjectManager.getProgrammerList();
List<Double> scheduleList = new ArrayList<>();
for (Programmer programmer : programmerList)
scheduleList.add(programmer.getSchedule());
return scheduleList.stream().collect(Collectors.averagingDouble(Double::doubleValue));
/**
* 获取项目进度
* 写法3
*/
public static Double getAvgSchedule3()
return ProjectManager.getProgrammerList().stream().mapToDouble( Programmer::getSchedule ).average().orElse(0d);
/**
* 项目预计完成时间
*
* 获取项目组内开发人员最晚完成时间即可
* 写法1
*/
public static Date getCompletePlanTime1()
List<Programmer> programmerList = ProjectManager.getProgrammerList();
List<Date> dateList = new ArrayList<>();
for (Programmer programmer : programmerList)
dateList.add(programmer.getCompletePlanTime());
return dateList.stream().max(Date::compareTo).get();
/**
* 项目预计完成时间
*
* 获取项目组内开发人员最晚完成时间即可
* 写法2
*/
public static Date getCompletePlanTime2()
return ProjectManager.getProgrammerList().stream().map(Programmer::getCompletePlanTime).max(Date::compareTo).get();
通过部门经理管理所有程序员,项目经理只提供了非常简单的信息,都是由部门经理类来操作,也就是说,一切事宜都是部门经理和程序员沟通,那,要项目经理干啥?部门经理管理10多个项目,上百号人,岂不是得累死…是的,你违反了迪米特法则~~
四、通过迪米特法则改善代码
部门经理直接调用项目经理类中的方法,获取项目名称,项目进展,预计完成时间等信息。
这样一来,整个功能逻辑就非常清晰了。
1、项目经理类
package com.guor.beanutil.principle.dimit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
public class ProjectManager
// 姓名
private String name;
// 项目
private String project;
// 进度
private String schedule;
// 计划完成时间
private String completePlanTime;
// 项目开发人员
private static List<Programmer> programmerList;
static
programmerList = new ArrayList<>();
programmerList.add(new Programmer("哪吒","哪吒闹海","技术选型,框架搭建",0.5,Programmer.getDate("2022-08-20")));
programmerList.add(new Programmer("妲己","哪吒闹海","前端",0.3,Programmer.getDate("2022-08-25")));
programmerList.add(new Programmer("敖丙","哪吒闹海","权限项目",0.2,Programmer.getDate("2022-08-31")));
programmerList.add(new Programmer("申公豹","哪吒闹海","管理模块",0.2,Programmer.getDate("2022-08-31")));
programmerList.add(new Programmer("二郎神","哪吒闹海","数据迁移",0.1,Programmer.getDate("2022-09-05")));
public static List<Programmer> getProgrammerList()
return programmerList;
/**
* 项目列表
*/
public static List<String> getProjects()
return ProjectManager.getProgrammerList().stream().map(Programmer::getProject).collect(Collectors.toList());
/**
* 获取项目进度
*/
public static Double getAvgSchedule()
return ProjectManager.getProgrammerList().stream().mapToDouble( Programmer::getSchedule ).average().orElse(0d);
/**
* 项目预计完成时间
*
* 获取项目组内开发人员最晚完成时间即可
*/
public static Date getCompletePlanTime()
return ProjectManager.getProgrammerList().stream().map(Programmer::getCompletePlanTime).max(Date::compareTo).get();
2、部门经理类
package com.guor.beanutil.principle.dimit;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class DepartmentManager
public static Map<String, Object> getProjectInfo()
Map<String, Object> map = new HashMap<>();
String project = ProjectManager.getProjects().get(0);
Double schedule = ProjectManager.getAvgSchedule();
Date completePlanTime = ProjectManager.getCompletePlanTime();
map.put("项目",project);
map.put("项目进度",schedule);
map.put("预计完成时间",completePlanTime);
return map;
3、控制台输出
迪米特法则虽然看似简单,但如果想在实际项目开发中,将各模块、功能规划的井井有条,运用的炉火纯青、恰到好处,真的很难。反复阅读,仔细体会。
设计模式系列文章:
以上是关于java设计模式4,不要和陌生人说话的主要内容,如果未能解决你的问题,请参考以下文章