在咱們剛開始學習編程的時候,一般會將全部的方法都聲明爲public,例如:html
package com.fanqiekt.principle.lod;
/**
* 廚師
*
* @author 番茄課堂-懶人
*/
public class Chef{
public String flavour = "祕製調料XXX";
/**
* 作飯
* @param dishName 下單的菜名
*/
public void cooking(String dishName) {
System.out.println("開始烹飪:"+dishName);
switch (dishName){
case "西紅柿炒雞蛋":
cookingTomato();
break;
case "酸辣土豆絲":
cookingPotato();
break;
}
System.out.println(dishName + "出鍋");
}
/**
* 炒西紅柿雞蛋
*/
public void cookingTomato() {
System.out.println("放入調料:" + flavour);
System.out.println("先炒雞蛋");
System.out.println("再炒西紅柿");
System.out.println("...");
}
/**
* 炒酸辣土豆絲
*/
public void cookingPotato() {
System.out.println("放入調料:" + flavour);
System.out.println("先放蔥薑蒜");
System.out.println("再放土豆絲");
System.out.println("...");
}
}
複製代碼
廚師類。程序員
package com.fanqiekt.principle.lod;
/**
* 客人
* @Author: 番茄課堂-懶人
*/
public class Client {
public static void main(String[] args){
Chef chef = new Chef();
chef.cooking("西紅柿炒雞蛋");
System.out.println("-------");
chef.cooking("酸辣土豆絲");
}
}
複製代碼
客人類。編程
這樣作好很差?bash
你們能夠先思考下。app
咱們先來看一下迪米特法則的定義。學習
又稱爲最少知識原則。優化
一個軟件實體應當儘量少地與其餘實體發生相互做用。ui
這個比較好理解,一個類儘量少的與其餘的類產生關聯,低耦合,高內聚嘛。spa
迪米特法則包含兩種角色:依賴者與被依賴者。code
咱們回到疑惑中的問題,Chef類好很差?
首先,Chef類的角色是被依賴者。
它暴露了flavour屬性,這是存在問題的,有哪一個廚師願意把本身的獨家配方公開出去啊。
並且它還暴露了依賴者並不關心cookingTomato、cookingPotato兩個方法。
對於依賴者來講,我只須要調用cooking方法就能夠了,至於菜具體怎麼作,就與我無關了。
而且暴露的話,程序員也容易懵逼,這兩個方法是幹嗎的?我要不要研究下?
因此,
從被依賴者的角度來講:只暴露應該暴露的方法或者屬性。
有個簡單的套路:
能夠用private就毫不用protected,能夠用protected就毫不用public。
那Client類總沒什麼問題了吧。
確實,乍一看感受沒有任何問題的,再乍乍一看仍是感受沒有問題。。。
它的不合適不是從語法調用方面看的,而是從依賴關係。
客人是不能夠直接依賴廚師的,而應該依賴服務員。
在實際項目中,極可能會存在客人類依賴了廚師類、服務員類,而服務員類又依賴了廚師類。
這會讓代碼很是混亂,也違背了迪米特法則。
因此,
從依賴者的角度來講:只依賴應該依賴的對象。
咱們按照迪米特法則優化下代碼。
package com.fanqiekt.principle.lod;
/**
* 廚師
*
* @author 番茄課堂-懶人
*/
public class Chef{
private String flavour = "祕製調料XXX";
/**
* 作飯
* @param dishName 下單的菜名
*/
public void cooking(String dishName) {
System.out.println("開始烹飪:"+dishName);
switch (dishName){
case "西紅柿炒雞蛋":
cookingTomato();
break;
case "酸辣土豆絲":
cookingPotato();
break;
}
System.out.println(dishName + "出鍋");
}
/**
* 炒西紅柿雞蛋
*/
private void cookingTomato() {
System.out.println("放入調料:" + flavour);
System.out.println("先炒雞蛋");
System.out.println("再炒西紅柿");
System.out.println("...");
}
/**
* 炒酸辣土豆絲
*/
private void cookingPotato() {
System.out.println("放入調料:" + flavour);
System.out.println("先放蔥薑蒜");
System.out.println("再放土豆絲");
System.out.println("...");
}
}
複製代碼
flavour聲明爲private,其餘類就不可訪問了,避免泄漏祕製調料。
cookingTomato、cookingPotato聲明爲private
cooking須要依賴者調用,因此依舊爲public。
package com.fanqiekt.principle.lod;
/**
* 服務員
*
* @author 番茄課堂-懶人
*/
public class Waiter {
private Chef chef = new Chef();
/**
* 點餐
* @param dishName 餐名
*/
public void order(String dishName) {
System.out.println("客人點餐:"+dishName);
chef.cooking(dishName);
System.out.println(dishName+"上桌啦,請您品嚐!");
}
}
複製代碼
服務員類,依賴了Chef對象,並聲明爲private。
package com.fanqiekt.principle.lod;
/**
* 客人
* @Author: 番茄課堂-懶人
*/
public class Client {
public static void main(String[] args){
Waiter waiter = new Waiter();
waiter.order("西紅柿炒雞蛋");
System.out.println("-------");
waiter.order("酸辣土豆絲");
}
}
複製代碼
客人類,依賴了Waiter類。。
客人點餐:西紅柿炒雞蛋
開始烹飪:西紅柿炒雞蛋
放入調料:祕製調料XXX
先炒雞蛋
再炒西紅柿
...
西紅柿炒雞蛋出鍋
西紅柿炒雞蛋上桌啦,請您品嚐!
-------
客人點餐:酸辣土豆絲
開始烹飪:酸辣土豆絲
放入調料:祕製調料XXX
先放蔥薑蒜
再放土豆絲
...
酸辣土豆絲出鍋
酸辣土豆絲上桌啦,請您品嚐!
複製代碼
運行結果。
下降風險
避免不應暴露的方法或者屬性暴露,從而規避風險。
避免依賴關係過於混亂。
接下來,請您欣賞迪米特法則的原創歌曲。
嘻哈說:迪米特法則
做曲:懶人
做詞:懶人
Rapper:懶人
哥們是個大廚
身材有些發福
您可讓我作飯甚至是打滷
但您無權知曉我具體是油煎炸煮
這是個人祕密才能把客人抓住
這就是最小知識原則的迪米特法則
一個實體盡少與其餘產生瓜葛
依賴者只依賴應該依賴的對象絕對能夠減小bug
被依賴者只暴露該暴露的屬性還有方法呢
把風險被下降絕對不多是假的
複製代碼
閒來無事聽聽曲,知識已填腦中去;
學習複習新方式,頭戴耳機不小覷。
番茄課堂,學習也要酷。