迪米特法則——合理的封裝
title: 迪米特法則——合理的封裝
date: 2016-10-22 18:55:36
tags:
- Java
- 設計模式
categories: 設計模式
背景
以服務員,客戶,錢包為載體,模擬一個付款過程,闡述不恰當的封裝行為。
說明合理封裝的一般過程以及不合理封裝所表現的一般形式,介紹迪米特法則相關的基本內容,遵循迪米特法則對問題程式碼進行重構。
看似沒有問題的問題
先看一個簡單程式碼,分別描述錢包、客戶、服務員:
public class Wallet {
private double value;
public double getTotalMoney() {
return value;
}
public void setTotalMoney(double newValue) {
value = newValue;
}
public void addMoney(double deposit) {
value += deposit;
}
public void subtractMoney(double debit) {
value -= debit;
}
// 省略其它欄位,方法
}
public class Customer {
private Wallet myWallet;
// 省略其它欄位,方法
}
public class Paperboy {
private Customer myCustomer;
public void pay(double payment) {
Wallet theWallet = myCustomer.getWallet();
if (theWallet.getTotalMoney() > payment) {
theWallet.subtractMoney(payment);
} else {
//money not enough
}
}
}
一眼看過去,沒毛病。幾個基本的簡單類在Paperboy的pay方法中實現了簡單的業務邏輯,但翻譯成“人類語言”就有點問題了:
業務的第一步造作:通過客戶獲取其錢包。
等等這樣真的好嗎?現實生活中彷彿講不通啊,程式設計中其實違反了迪米特法則。
聽到迪米特法則那一瞬間,我想到的是各種設計模式概念,尷尬的是就是想不起迪米特到底是個啥!
迪米特法則
迪米特法則(最小知識法則,強調專注性):
任何一個物件或者方法,它應該只能呼叫下列物件:
- 該物件本身和物件的屬性
- 作為引數傳進方法的物件
- 在方法內建立的物件
這下好像清晰多了,其實再通俗一點上面的程式碼就是違反了封裝的原則。
合理的封裝分為兩步:
-
分辨職責
- 依據:資料與行為應該封裝在一起(資訊專家模式)
- 過程:職責操作哪些資料,資料在哪個(些)類,進而確定職責在哪個類
- 判別哪些是實現細節,哪些是可以公開的介面,以保證對細節的合理隱藏
不良封裝造成的結果:Feature Envy(依戀情結)
不良封裝可能的程式碼樣式:
obj1.obj1_fun().obj2_fun();
類似鏈式的方法呼叫,但方法返回的是不同物件,這時候的程式碼很有可能是不良封裝,違反迪米特法則了。
問題的解決
上面程式碼良好的封裝示例:
public class Customer {
private Wallet myWallet;
public void pay(float payment) {
Wallet theWallet = myWallet;
if (theWallet.getTotalMoney() > payment) {
theWallet.subtractMoney(payment);
} else {
//money not enough
}
}
}
public class Paperboy {
private Customer myCustomer;
public void pay(float payment) {
myCustomer.pay(payment);
}
}
相關文章
- 什麼是迪米特法則?
- 設計原則之【迪米特法則】
- 軟體設計原則—迪米特法則
- 嘻哈說:設計模式之迪米特法則設計模式
- 設計模式的七大原則(6) --迪米特法則設計模式
- 設計模式六大原則(五)----迪米特法則設計模式
- 2分鐘通俗理解迪米特法則,架構設計築基必看架構
- [譯] 更可靠的 React 元件:合理的封裝React元件封裝
- dijkstra迪傑斯特拉演算法(鄰接表法)演算法
- 迪傑斯特拉與spfa
- [記錄] 通用封裝函式——四則運算封裝函式
- java 的 四 個 基 本 特 性 ——封裝 繼承 多型 抽象Java封裝繼承多型抽象
- 【封裝小技巧】is 系列方法的封裝封裝
- 【JavaScript框架封裝】公共框架的封裝JavaScript框架封裝
- 省米匯-品牌折扣特賣
- 最短路-迪傑斯特拉(dijkstra)
- 如何用利特爾法則調整執行緒池大小執行緒
- 如何使用利特爾法則調整執行緒池大小執行緒
- Dapper的封裝、二次封裝、官方擴充套件包封裝,以及ADO.NET原生封裝APP封裝套件
- 【封裝那些事】 缺失封裝封裝
- 封裝、許可權修飾符、封裝的案例封裝
- 【封裝小技巧】列表處理函式的封裝封裝函式
- 記一則iOS封裝SDK的開發過程之WebView與JS的互動iOS封裝WebViewJS
- 封裝封裝
- Ladda的vue封裝Vue封裝
- 【封裝小技巧】數字處理函式的封裝封裝函式
- js 動態新增class封裝(es6語法)JS封裝
- 設計原則之【開放封閉原則】
- 新手學習的法則
- Johnson法則
- Flutter 封裝:富文字 RichText 極簡封裝Flutter封裝
- 封裝Vue 的 SVG 元件封裝VueSVG元件
- 一、類的封裝性封裝
- 如何封裝安全的go封裝Go
- 封裝redux中的createStore封裝Redux
- Vue Axios 的封裝使用VueiOS封裝
- IQueryable的簡單封裝封裝
- 易理解的Promise封裝Promise封裝