也叫最少知道原则,Least Knowledge Principle
定义
一个对象应该对其他对象有最少的了解,通俗的讲,一个类应该对自己需要耦合或调用的类知道得最少,被耦合或调用的类的内部是多么复杂和我没有关系,我只要知道提供的public方法,就知道这么多,其他的都不关心。
四层含义
迪米特法则对类的低耦合提出了明确的要求
只和直接的朋友交流
两个对象之间的耦合成为朋友关系。
举个栗子:
老师向体育委员发命令,让他清点女生人数
/*
* 老师类
*/
public class Teacher {
//老师对学生发布命令,清点一下女生
public void commond(GroupLeader groupLeader) {
List<Girl> listGirl = new ArrayList<Girl>();
//初始化女生
for (int i = 0;i<20;i++) {
listGirl.add(new Girl());
}
//告诉体育委员开始执行清查任务
groupLeader.countGirls(listGirl);
}
}
/*
* 体育委员
*/
public class GroupLeader {
//清查女生数量
public void countGirls(List<Girl> listGirls) {
System.out.println("女生的数量是:"+listGirls.size());
}
}
/*
* 女生
*/
public class Girl {
}
/*
* 模拟老师命令体育委员清点女生人数场景
*/
public class Client {
public static void main(String[] args) {
Teacher teacher = new Teacher();
//老师发布命令
teacher.commond(new GroupLeader());
}
}
发现Teacher的直接朋友是GroupLeader但是方法间却用了不是直接朋友的对象Girl,commond方法时teacher的方法,teacher却不知道自己与Girl有了依赖,这是不允许的。
现在要将这个依赖关系去掉。
/*
* 老师类
*/
public class Teacher {
//老师对学生发布命令,清点一下女生
public void commond(GroupLeader groupLeader) {
//告诉体育委员开始执行清查任务
groupLeader.countGirls();
}
}
/*
* 体育委员
*/
public class GroupLeader {
private List<Girl> listGirls ;
public GroupLeader(List<Girl> listGirls ) {
this.listGirls = listGirls;
}
//清查女生数量
public void countGirls() {
System.out.println("女生的数量是:"+this.listGirls.size());
}
}
/*
* 模拟老师命令体育委员清点女生人数场景
*/
public class Client {
public static void main(String[] args) {
//女生群体
List<Girl> listGirls = new ArrayList<Girl>();
Teacher teacher = new Teacher();
//老师发布命令
teacher.commond(new GroupLeader(listGirls));
}
}
避开了Teacher类对陌生类的访问,降低了耦合性,提高了系统的健壮性。
朋友间是有距离的
类之间的耦合关系不能过于牢固,即使是朋友之间也不能无话不说。
举个栗子:
/*
* 模拟安装软件动作,根据向导,第一个动作完毕下一个动作运行
*/
public class InstallSoftware {
public void installWizard(Wizard wizard) {
int first = wizard.first();
if(first > 50) {
int second = wizard.second();
if(second>50) {
int third = wizard.third();
if(third > 50) {
wizard.first();
}
}
}
}
}
/*
* 向导类
*/
public class Wizard {
private Random rand = new Random(System.currentTimeMillis());
//第一步
public int first() {
System.out.println("执行第一个方法");
return rand.nextInt(100);
}
//第二步
public int second() {
System.out.println("执行第二个方法");
return rand.nextInt(100);
}
//第三步
public int third() {
System.out.println("执行第三个方法");
return rand.nextInt(100);
}
}
/*
* 场景类
*/
public class ClientForInstall {
public static void main(String[] args) {
InstallSoftware invoker = new InstallSoftware();
invoker.installWizard(new Wizard());
}
}
如果Wizard类中first方法返回值变了,那么InstallSoftware类也要发生变化,这样过于依赖了。
可以让public的方法减少,让private或者protected的方法多一些。
修改后:
/*
* 模拟安装软件动作,根据向导,第一个动作完毕下一个动作运行
*/
public class InstallSoftware {
public void installWizard(Wizard wizard) {
wizard.installWizard();
}
}
/*
* 向导类
*/
public class Wizard {
private Random rand = new Random(System.currentTimeMillis());
//第一步
private int first() {
System.out.println("执行第一个方法");
return rand.nextInt(100);
}
//第二步
private int second() {
System.out.println("执行第二个方法");
return rand.nextInt(100);
}
//第三步
private int third() {
System.out.println("执行第三个方法");
return rand.nextInt(100);
}
//软件安装过程
public void installWizard() {
int first = this.first();
if(first > 50) {
int second = this.second();
if(second>50) {
int third = this.third();
if(third > 50) {
this.first();
}
}
}
}
}
是自己的就是自己的
如果一个方法放在本类中不增加类间关系,对本类不产生负面影响,那么就放在本类中。
谨慎使用Serializable
如果一个项目使用了远程方法调用,这个对象就必须实现Serializable接口,也就是需要把网络传输的对象序列化,否则就会出现异常。突然,客户端的VO修改了一个属性的访问权限,private变为public访问权限变大了,如果程序上没有变更,就会报序列化失败。