在上一讲中迪米特法则没有细讲,补充下。
一、迪米特法则的定义
1、最少知识原则
迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。英文简写为: LOD。
迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的朋友类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。
设计模式的门面模式(Facade)和中介模式(Mediator),都是迪米特法则应用的例子。
2、狭义的迪米特法则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
朋友的确定:
1)当前对象本身(this)
2)类中的字段(如果字段是一个集合,那么集合中的元素也是朋友)
3)方法的参数
4)方法的返回值
5)方法中临时实例化出来的对象
任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”;否则就是“陌生人”。
3、狭义的迪米特法则的缺点:
在系统里造出大量的小方法,这些方法仅仅是传递间接的调用,与系统的业务逻辑无关。
遵循类之间的迪米特法则会是一个系统的局部设计简化,因为每一个局部都不会和远距离的对象有直接的关联。但是,这也会造成系统的不同模块之间的通信效率降低,也会使系统的不同模块之间不容易协调。
4、广义的迪米特法则在类的设计上的体现:
优先考虑将一个类设置成不变类。
尽量降低一个类的访问权限。
谨慎使用Serializable。
尽量降低成员的访问权限。
二、迪米特法则的应用
门面模式和中介者模式是迪米特法则的应用。
1、实现计算机的关机功能
/**
* @Title Test
* @Description
* @Author lvaolin
* @Date 2021/12/12 22:49
**/
class User{
public void showDownComputer(){
Computer computer = new Computer();
computer.saveData();
computer.exitProcess();
computer.powerOff();
//违反了最少知道原则
}
}
class Computer{
public void saveData(){
System.out.println("保存数据");
}
public void exitProcess(){
System.out.println("退出进程");
}
public void powerOff(){
System.out.println("断电");
}
}
使用门面模式改进后
class User{
public void showDownComputer(){
Computer computer = new Computer();
computer.shutDown(); //只调用一个方法即可,无需关注内部细节
}
}
class Computer{
public void shutDown(){
this.saveData();
this.exitProcess();
this.powerOff();
}
private void saveData(){
System.out.println("保存数据");
}
private void exitProcess(){
System.out.println("退出进程");
}
private void powerOff(){
System.out.println("断电");
}
}
2、和陌生人通信的例子
/**
* @Date 2021/12/12 22:49
**/
class User{
private Date date = new Date();
private List<String> list = new ArrayList<>();
public boolean showDownComputer(Computer computer){
StringBuilder log = new StringBuilder(this.date.toString());
Power power = computer.getPower();
power.off();//和陌生人通信了,违反迪米特法则
return true;
}
}
class Computer{
public Power getPower() {
return new Power();
}
}
class Power{
void on(){}
void off(){ }
}
解决方法:
1)通过朋友转发
class User{
private Date date = new Date();
private List<String> list = new ArrayList<>();
public boolean showDownComputer(Computer computer){
StringBuilder log = new StringBuilder(this.date.toString());
computer.off();//只和朋友通信
return true;
}
}
class Computer{
public void off(){
Power power = new Power();
power.off();
}
}
class Power {
public void on(){}
public void off(){ }
}
2)通过将陌生人发展成为自己的朋友再通信
class User{
private Date date = new Date();
private List<String> list = new ArrayList<>();
public boolean showDownComputer(Computer computer){
StringBuilder log = new StringBuilder(this.date.toString());
Power power = computer.getPower();
this.powerOff(power);
return true;
}
pubic void powerOff(Power power) {//将陌生人变成了朋友
power.off();//和朋友通信
}
}
class Computer{
public Power getPower() {
return new Power();
}
}
class Power{
void on(){}
void off(){ }
}
3)和抽象陌生人通信
class User{
private Date date = new Date();
private List<String> list = new ArrayList<>();
public boolean showDownComputer(Computer computer){
StringBuilder log = new StringBuilder(this.date.toString());
IPower iPower = computer.getPower();
iPower.off();//和接口通信
return true;
}
}
class Computer{
public IPower getPower() { return new Power(); }
}
interface IPower{
void on();
void off();
}
class Power implements IPower{
@Override
public void on(){}
@Override
public void off(){ }
}