>[success] # 最少知识 -- 迪米特法则(LOD)
* **迪米特法则**:也叫`最少知识原则`,如果两个类不必彼此直接通信,那这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
*****
* 迪米特法则首先强调的前提是在类的结构设计上,每一个类都尽量降低成员的访问权限,也就是说一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。迪米特法则的根本思想是强调类之间的松耦合。类之间的耦合越弱,越有利于复用,一个处于弱耦合的类被修改,不会对有关系的类造成波及,也就是信息的隐藏促进了软件的复用。
>[info] ## 购物案例
假设一个在超市购物的场景:顾客选好商品后,到收银台找收银员结账。这里我们定义一个顾客类(Customer)、收银员类(PaperBoy )、钱包类(Wallet ),示例代码如下(逻辑是 收银员获取顾客钱包,从顾客钱包中检查钱是否够支付的,够就从钱包拿钱,不够就是就把钱包还给顾客)
~~~
//顾客
public class Customer {
private String firstName;
private String lastName;
private Wallet myWallet;
public String getFirstName(){
return firstName;
}
public String getLastName(){
return lastName;
}
public Wallet getWallet(){
return myWallet;
}
}
//钱包类
public class Wallet {
private float value;
public float getTotalMoney() {
return value;
}
public void setTotalMoney(float newValue) {
value = newValue;
}
public void addMoney(float deposit) {
value += deposit;
}
public void subtractMoney(float debit) {
value -= debit;
}
}
//收银员
public class Paperboy {
public void charge(Customer myCustomer, float payment) {
payment = 2f;
Wallet theWallet = myCustomer.getWallet();
if (theWallet.getTotalMoney() > payment) {
theWallet.subtractMoney(payment);
} else {
//钱不够的处理
}
}
}
~~~
* 逻辑看似荒诞,但违背了**迪米特法则**,`收银员的类`完全没必要和`钱包类`进行通信,如果非要使用`钱包类` 应该是通过第三者转发,钱包属于顾客,顾客才能作为中转使用钱包。
~~~
//顾客
public class Customer {
private String firstName;
private String lastName;
private Wallet myWallet;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Wallet getWallet() {
return myWallet;
}
public float pay(float bill) {
if (myWallet != null) {
if (myWallet.getTotalMoney() > bill) {
myWallet.subtractMoney(bill);
return bill;
}
}
return 0;
}
}
// 钱包类
public class Wallet {
private float value;
public float getTotalMoney() {
return value;
}
public void setTotalMoney(float newValue) {
value = newValue;
}
public void addMoney(float deposit) {
value += deposit;
}
public void subtractMoney(float debit) {
value -= debit;
}
}
// 收银员
public class PaperBoy {
public void charge(Customer myCustomer, float payment {
payment = 2f; // “我要收取2元!”
float paidAmount = myCustomer.pay(payment);
if (paidAmount == payment) {
// 说声谢谢,欢迎下次光临
} else {
// 可以稍后再来
}
}
}
~~~
>[danger] ##### 应用
[门面模式](https://baike.baidu.com/item/%E9%97%A8%E9%9D%A2%E6%A8%A1%E5%BC%8F/764642?fromModule=lemma_inlink)([Facade](https://baike.baidu.com/item/Facade/2954918?fromModule=lemma_inlink))和中介模式(Mediator),都是迪米特法则应用的例子