就一個(gè)類而言,應(yīng)該只有一個(gè)引起它變化的原因。
這里的所有觀點(diǎn)摘抄自《敏捷軟件開發(fā)原則、模式與實(shí)踐》,原著Robert C. Martin,鄧輝等譯。
職責(zé)分離
如果一個(gè)類承擔(dān)的職責(zé)過多,就等于把這些職責(zé)都耦合在了一起,一個(gè)職責(zé)的變化可能會削弱或者抑制這個(gè)類完成其他職責(zé)的能力。這種耦合會導(dǎo)致脆弱的設(shè)計(jì),當(dāng)變化發(fā)生時(shí),設(shè)計(jì)會受到意想不到的破壞。
類比于人,一個(gè)擁有多個(gè)角色的人,假如他既要。。。
例如書中的Retangle類,就具有繪制矩形和計(jì)算矩形面積的功能。圖中可以看出,這兩個(gè)功能分別由不同的應(yīng)用來使用。
問題
如果我只是一個(gè)計(jì)算矩形面積的程式,并沒有圖形界面,理論上不需要引入繪制圖形的GUI庫(GUI的庫一般比較大并且有很多依賴)。但是由于Retangle類具有繪制矩形的功能,所以勢必要引入GUI庫。對于C++來說就需要連接GUI的代碼,這會浪費(fèi)編譯、鏈接以及消耗部分的內(nèi)存。如果是Java程序,GUI的.class文件就必須被部署到目標(biāo)平臺。
如果GraphicalApplication的改變導(dǎo)致Rectangle也發(fā)生了變化,那么,這個(gè)變化會迫使我們重新構(gòu)建、測試以及部署ComputationalGeometryApplication。
解決方案
一個(gè)較好的設(shè)計(jì)是把這兩個(gè)職責(zé)分離到如下兩個(gè)不同的類中。實(shí)現(xiàn)解耦。
可以看到,計(jì)算矩形面積的應(yīng)用,只需要調(diào)用Geometric Rectangle來計(jì)算,這時(shí)候就不需要用到GUI庫了。
什么是職責(zé)
職責(zé)被定義為"變化的原因"。如果有多個(gè)導(dǎo)致類變化的原因,那么這個(gè)類就具有多于一個(gè)的職責(zé)。
很多時(shí)候,我們很難去區(qū)分到底是否具有多個(gè)職責(zé),是否有多個(gè)原因引起了累的變化。下面通過一個(gè)modem的類,來說明什么情況下會區(qū)分出職責(zé)。
考慮如下的代碼:
interface Modem {
public void dial(String pno);
public void hanup();
public void send(char c);
public void recv();
}
可以看出這個(gè)類中包含了兩個(gè)部分,一個(gè)是連接處理,一個(gè)是數(shù)據(jù)通信。
那一定要進(jìn)行拆分么?
其實(shí)不一定,是否需要拆分取決于變化。
- 當(dāng)變化發(fā)生,只影響其中一個(gè)職責(zé),那就需要拆分
- 如果變化都影響到這兩個(gè)職責(zé),那就不需要拆分