文章目錄
- 1.迪米特法則
- 2.高内聚
- 3.松耦合
- 4.代碼
- 5.總結
1.迪米特法則
- 迪米特法則的英文翻譯是:Law of Demeter,縮寫是 LOD。
- 單從這個名字上來看,我們完全猜不出這個原則講的是什麼。不過,它還有另外一個更加達意的名字,叫作最小知識原則,英文翻譯為:The Least Knowledge Principle。
- 它不像 SOLID、KISS、DRY 原則那樣,人盡皆知,但它卻非常實用。利用這個原則,能夠幫我們實作代碼的“高内聚、松耦合”
- “高内聚、松耦合”是一個非常重要的設計思想,能夠有效地提高代碼的可讀性和可維護性,縮小功能改動導緻的代碼改動範圍
- 很多設計原則都以實作代碼的“高内聚、松耦合”為目的,比如單一職責原則、基于接口而非實作程式設計等
- “高内聚、松耦合”是一個比較通用的設計思想,可以用來指導不同粒度代碼的設計與開發,比如系統、子產品、類,甚至是函數,也可以應用到不同的開發場景中,比如微服務、架構、元件、類庫等
-
(也就是定義中的“有限知識”)不該有直接依賴關系的類之間,不要有依賴;有依賴關系的類之間,盡量隻依賴必要的接口
2.高内聚
就是指相近的功能應該放到同一個類中,不相近的功能不要放到同一個類中。相近的功能往往會被同時修改,放到同一個類中,修改會比較集中,代碼容易維護
3.松耦合
4.代碼
public class Serialization {
public String serialize(Object object) {
String serializedResult = ...;
//...
return serializedResult;
}
public Object deserialize(String str) {
Object deserializedResult = ...;
//...
return deserializedResult;
}
}
- 假設在我們的項目中,有些類隻用到了序列化操作,而另一些類隻用到反序列化操作。
- 那基于迪米特法則後半部分“有依賴關系的類之間,盡量隻依賴必要的接口”,隻用到序列化操作的那部分類不應該依賴反序列化接口。同理,隻用到反序列化操作的那部分類不應該依賴序列化接口。
public class Serializer {
public String serialize(Object object) {
String serializedResult = ...;
...
return serializedResult;
}
}
public class Deserializer {
public Object deserialize(String str) {
Object deserializedResult = ...;
...
return deserializedResult;
}
}
- 将 Serialization 類拆分為兩個更小粒度的類,一個隻負責序列化(Serializer 類),一個隻負責反序列化(Deserializer 類)。拆分之後,使用序列化操作的類隻需要依賴 Serializer 類,使用反序列化操作的類隻需要依賴 Deserializer 類
- 管拆分之後的代碼更能滿足迪米特法則,但卻違背了高内聚的設計思想。高内聚要求相近的功能要放到同一個類中,這樣可以友善功能修改的時候,修改的地方不至于過于分散。對于剛剛這個例子來說,如果我們修改了序列化的實作方式,比如從 JSON 換成了 XML,那反序列化的實作邏輯也需要一并修改。在未拆分的情況下,我們隻需要修改一個類即可
public interface Serializable {
String serialize(Object object);
}
public interface Deserializable {
Object deserialize(String text);
}
public class Serialization implements Serializable, Deserializable {
@Override
public String serialize(Object object) {
String serializedResult = ...;
...
return serializedResult;
}
@Override
public Object deserialize(String str) {
Object deserializedResult = ...;
...
return deserializedResult;
}
}
public class DemoClass_1 {
private Serializable serializer;
public Demo(Serializable serializer) {
this.serializer = serializer;
}
//...
}
public class DemoClass_2 {
private Deserializable deserializer;
public Demo(Deserializable deserializer) {
this.deserializer = deserializer;
}
//...
}
- 盡管我們還是要往 DemoClass_1 的構造函數中,傳入包含序列化和反序列化的 Serialization 實作類,但是,我們依賴的 Serializable 接口隻包含序列化操作,DemoClass_1 無法使用 Serialization 類中的反序列化接口,對反序列化操作無感覺,
- 這也就符合了迪米特法則後半部分所說的“依賴有限接口”的要求。
5.總結
- 展現了“基于接口而非實作程式設計”的設計原則,結合迪米特法則,我們可以總結出一條新的設計原則,那就是“基于最小接口而非最大實作程式設計”
- 目的都是實作高内聚低耦合,但是出發的角度不一樣,單一職責是從自身提供的功能出發,迪米特法則是從關系出發,針對接口而非實作程式設計是使用者的角度,殊途同歸