定義
迪米特法則也叫最少知道原則逾滥,即一個對象應(yīng)該對其他對象有最少的了解寨昙,一個類對需要耦合的類知道的最少,也即高內(nèi)聚低耦合尚卫。
四層含義
- 只和朋友交流(類只和必須關(guān)聯(lián)的類去耦合)
- 朋友之間也是有距離的(耦合類之間減少)
- 是自己的就是自己的
- 謹(jǐn)慎使用Serializable接口
只和朋友交流
public class Girl {
}
public class GroupLeader {
public void countGirls(List<Girl> listGirls) {
System.out.println("女生數(shù)量是:" + listGirls.size());
}
}
public class Teacher {
public void command(GroupLeader groupLeader) {
List listGirls = new ArrayList();
//初始化女生
for (int i = 0; i < 20; i++) {
listGirls.add(new Girl());
}
//告訴體育委員開始執(zhí)行清查任務(wù)
groupLeader.countGirls(listGirls);
}
}
public class Client {
public static void main(String[] args) {
Teacher teacher = new Teacher();
//老師發(fā)布命令
teacher.command(new GroupLeader());
}
}
我們看上面這個例子里面Teacher既跟GroupLeader交互刹泄,也跟Gril直接交互。這明顯違背了只跟朋友交互的問題盅蝗。
public class Girl {
}
public class GroupLeader {
private List<Girl> listGirls;
//傳遞全班的女生進(jìn)來
public GroupLeader(List<Girl> listGirls) {
this.listGirls = listGirls;
}
//清查女生數(shù)量
public void countGirls() {
System.out.println("女生數(shù)量是:" + listGirls.size());
}
}
public class Teacher {
//老師對學(xué)生發(fā)布命令墩莫,清一下女生
public void command(GroupLeader groupLeader) {
//告訴體育委員開始執(zhí)行清潔任務(wù)
groupLeader.countGirls();
}
}
public class Client {
public static void main(String[] args) {
//產(chǎn)生一個女生群體
List<Girl> listGirls = new ArrayList<>();
//初始化女生
for (int i = 0; i < 20; i++) {
listGirls.add(new Girl());
}
Teacher teacher = new Teacher();
//老師發(fā)布命令
teacher.command(new GroupLeader(listGirls));
}
}
修改后的類圖是
我們發(fā)現(xiàn)代碼更改后Teacher類只跟GroupLeader溝通,不再需要跟Girl類耦合裂问。
朋友圈也是有距離的
public class Wizard {
private Random random = new Random(System.currentTimeMillis());
//第一步
public int first() {
System.out.println("執(zhí)行第一個方法...");
return random.nextInt(100);
}
//第二步
public int second() {
System.out.println("執(zhí)行第二個方法...");
return random.nextInt(100);
}
//第三步
public int third() {
System.out.println("執(zhí)行第三個方法...");
return random.nextInt(100);
}
}
public class InstallSoftware {
public void installWizard(Wizard wizard) {
int first = wizard.first();
//根據(jù)first返回的結(jié)果,看是否執(zhí)行second
if (first > 50) {
int second = wizard.second();
//根據(jù)second返回的結(jié)果椭更,看是否執(zhí)行third
if (second > 50) {
int third = wizard.third();
//根據(jù)third返回的結(jié)果蛾魄,看是否執(zhí)行first
if (third > 50) {
wizard.first();
}
}
}
}
}
public class Client {
public static void main(String[] args) {
InstallSoftware invoker = new InstallSoftware();
invoker.installWizard(new Wizard());
}
}
我們看上面這一段邏輯就是很簡單的一個安裝軟件的過程,似乎一眼看起來并沒有問題茉稠,但其實wizard自身的安裝邏輯方法很多都暴露給了調(diào)用方把夸,如果任意一個安裝方法返回類型變化必然會引起調(diào)用方變化恋日,實際安裝的變化應(yīng)該隱藏在wizard內(nèi)部,所以我們修改一下岂膳。
public class Wizard {
private Random random = new Random(System.currentTimeMillis());
//第一步
private int first() {
System.out.println("執(zhí)行第一個方法...");
return random.nextInt(100);
}
//第二步
private int second() {
System.out.println("執(zhí)行第二個方法...");
return random.nextInt(100);
}
//第三步
private int third() {
System.out.println("執(zhí)行第三個方法...");
return random.nextInt(100);
}
public void installWizard( ) {
int first = first();
//根據(jù)first返回的結(jié)果谈截,看是否執(zhí)行second
if (first > 50) {
int second = second();
//根據(jù)second返回的結(jié)果簸喂,看是否執(zhí)行third
if (second > 50) {
int third = third();
//根據(jù)third返回的結(jié)果扼倘,看是否執(zhí)行first
if (third > 50) {
first();
}
}
}
}
}
public class InstallSoftware {
public void installWizard(Wizard wizard) {
wizard.installWizard();
}
}
public class Client {
public static void main(String[] args) {
InstallSoftware invoker = new InstallSoftware();
invoker.installWizard(new Wizard());
}
}
我們將wizard的安裝步驟方法改成private再菊,并將安裝步驟移到wizard中纠拔,迪米特法則要求類盡量不要對外公布太多的public方法和非靜態(tài)的public變量泛啸,盡量內(nèi)斂绿语。
是自己的就是自己的
在實際場景中我們會遇到一個方法放在本類中也可以,放在其他類中也沒有錯的情況候址,書中的建議是如果一個方法放在本類中吕粹,即不增加類間關(guān)系,也對本類不產(chǎn)生負(fù)面影響岗仑,那就放置在本類中匹耕,不過我們組在工作中是通過判讀這個方法能力應(yīng)該由誰來提供,在UML建模時就可以探討出來放在那里合適荠雕。
謹(jǐn)慎使用Serializable接口
Serializable接口主要用于遠(yuǎn)程方法調(diào)用中序列化一個對象進(jìn)行網(wǎng)絡(luò)傳輸稳其,如果客戶端的對象修改了對象屬性的權(quán)限驶赏,譬如從public修改成private,服務(wù)器上沒有做相應(yīng)變化時會序列化失敗既鞠。
思考與總結(jié)
我將迪米特法則簡單描述成是你的就是你的煤傍,不是你的你不要蚯姆,就算是你的你也得珍惜,這三句話分別對應(yīng)了前三個原則郭毕,我在實際工作中CR或者編程沒有想著說我要以六大原則去審視一下自己的代碼,在工作中通過UML模型圖以及控制好方法的權(quán)限沒啥問題就通過了敞峭,所以等開閉原則學(xué)完之后以六大原則審視一下自己負(fù)責(zé)的項目,看是否有優(yōu)化的地方睦疫,CR或者編寫時是否可以找到一套方法論去更好的校驗或評判葫松。