## 英文名稱:Low of Demeter,LoD
**定義**:一個對象應該對其他對象有最少的了解。只與直接的朋友通信。
**朋友關系**:每個對象都必然會與其他對象有耦合關系,兩個對象之間的耦合就稱為朋友關系。
**我的理解**:迪米特法則定義的是類之間的關系要盡量低耦合,一個類中的朋友不要太多,
這樣在后期代碼維護或更改時需要修改的地方也就不會太多了。
**一個例子**:
體育老師要求班長清點女生的人數。
體育老師類(Teacher):command(ClassMonitor classMonitor)方法
班長類(ClassMonitor):countGirl(List<Girl> listGirls)方法
女生類(Girl)

~~~
<span style="font-size:18px;">public class LoDTest {
public static void main(String[] args) {
new Teacher().command(new ClassMonitor());
}
}
class Teacher{
public void command(ClassMonitor classMonitor){
List<Girl> listGirls = new ArrayList<Girl>();
for(int i=0;i<10;i++){
listGirls.add(new Girl());
}
classMonitor.countGirl(listGirls);
}
}
class ClassMonitor{
public void countGirl(List<Girl> listGirls){
System.out.println("班長說:女生的數量是..."+listGirls.size());
}
}
class Girl{
}</span>
~~~
在Teacher類中,一個方法調用了兩個類的實例,Teacher類依賴于ClassMonitor和Girl類。
而Teacher類中的朋友類只有ClassMonitor,Girl類是定義在方法體內的方法,因此不屬于朋友類。
而迪米特法則告訴我們只與朋友類進行通信,所以這種設計方式違反了迪米特法則。
**朋友關系在java中的定義**:出現在成員變量,方法的輸入輸出類稱為成員朋友類,而出現在方法體內部的類不屬于朋友類。
**設計改進:**
去掉Teacher類中的Girl實例的創建,減少不必要的依賴關系。
使Teacher類只與直接朋友類ClassMonitor通信,而ClassMonitor類的直接朋友類是Girl類。

~~~
<span style="font-size:18px;">public class LoDTest {
public static void main(String[] args) {
List<Girl> listGirls = new ArrayList<Girl>();
for(int i=0;i<10;i++){
listGirls.add(new Girl());
}
new Teacher().command(new ClassMonitor(listGirls));
}
}
class Teacher{
public void command(ClassMonitor classMonitor){
classMonitor.countGirl();
}
}
class ClassMonitor{
List<Girl> listGirls;
public ClassMonitor(List<Girl> listGirls){
this.listGirls = listGirls;
}
public void countGirl(){
System.out.println("班長說:女生的數量是..."+listGirls.size());
}
}
class Girl{
}</span>
~~~
迪米特法則給類的低耦合提出了四個基本的要求
## 1、只和朋友類交流。
上述代碼已經陳述這句話的含義,就是說盡量避免一個類中依賴于多個類的情況,一個類中的方法只與朋友類進行通信。
## 2、朋友間也是有距離的。
類似于顯示生活中的情況,再親密的朋友,也會為對方留有私人空間。
在java中的實現思想就是:類A與類B之間有依賴關系,并在方法輸入或輸出中創建該類的實例,那么他們屬于朋友類,但是類A不可以過分操作類B的方法
**例如:**
模擬下載軟件中的過程,點擊下一步,完成下載軟件。
**實現方式**:
1、類InstallSoftware:有一個下載軟件的方法installWizard(Wizard wizard).
2、類Wizard:擁有first(),second(),third()方法。

~~~
public class LoDTest3 {
public static void main(String[] args) {
new InstallSoftware().installWizard(new Wizard());
}
}
class InstallSoftware{
public void installWizard(Wizard wizard){
int first = wizard.first();
boolean flag = false;
if(first > 50){
int second = wizard.second();
if(second>50){
int third = wizard.third();
if(third >50)
flag = wizard.over();
}
}
if(!flag)
System.out.println("下載失敗...");
}
}
class Wizard{
private Random rand = new Random();
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 boolean over(){
System.out.println("下載完成...");
return true;
}
}
~~~
**設計缺陷**:這里InstallSoftware類的朋友類是Wizard類,但是InstallSoftware類太過于依賴Wizard類, 如果Wizard類有所更改,那么InstallSoftware類就會進行更改。因此我們要避免不必要的修改。
**設計改進**:盡量減少朋友類的public接口,只為InstallSoftware類提供一個服務接口,在InstallSoftware類調用Wizard類時,只需要調用他的實現方法就可以了,而沒有必要替Wizard類去實現。

~~~
public class LoDTest3 {
public static void main(String[] args) {
new InstallSoftware(new Wizard()).installWizard();
}
}
class InstallSoftware{
private Wizard wizard;
public InstallSoftware(Wizard wizard){
this.wizard = wizard;
}
public void installWizard(){
wizard.installWizard();
}
}
class Wizard{
private Random rand = new Random();
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);
}
private boolean over(){
System.out.println("下載完成...");
return true;
}
public void installWizard(){
int first = first();
boolean flag = false;
if(first > 50){
int second = second();
if(second>50){
int third = third();
if(third >50)
flag = over();
}
}
if(!flag)
System.out.println("下載失敗...");
}
}
~~~
## 3、是自己的就是自己的
如果一個方法放在本類中,既不增加類間關系,也對本類不產生負面影響,那就放置在本類中。
## 4、謹慎使用serializable
這就話不太理解。在開發中我也很少用到過這個關鍵字。
我對迪米特法則的理解:迪米特法則定義的是類之間的設計的規范。也就是各自管理好自己類中的職責就行了。在開發中難免會遇到類之間的聯系,那么就要嚴格遵守迪米特法則,對為了需求的變更有很大的幫助。
- 前言
- 6大設計原則(一)---單一職責原則
- 6大設計原則(二)---里氏替換原則
- 6大設計原則(三)---依賴倒置原則
- 6大設計模式(四)----接口隔離原則
- 6大設計原則(五)---迪米特法則
- 6大設計原則(六)---開閉原則。
- 設計模式(一)---單例模式
- 設計模式(二)---工廠方法模式
- 設計模式(三)---抽象工廠模式
- 設計模式(四)---模板方法模式
- 設計模式(五)---建造者模式
- 設計模式(六)---代理模式
- 設計模式(七)---原型模式
- 設計模式(八)---中介者模式
- 設計模式(九)---命令模式
- 設計模式(十)---責任鏈模式
- 設計模式(十一)---裝飾模式
- 設計模式(十二)---策略模式
- 設計模式(十三)---適配器模式
- 設計模式(十四)---迭代器模式
- 設計模式(十五)---組合模式
- 設計模式(十六)---觀察者模式
- 設計模式(十七)---門面模式
- 設計模式(十八)---備忘錄模式
- 設計模式(十八)---訪問者模式
- 設計模式(二十)---狀態模式
- 設計模式(二十二)---享元模式
- 設計模式(二十三)---橋梁模式