>[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),都是迪米特法則應用的例子