一、定義。
SRP(Single Responsibility Principle):單一職責(zé)的原則:一個類應(yīng)該只有一個發(fā)生變化的原因。
每一個職責(zé)都是變化的軸線。當(dāng)需求變化時,該變化會反應(yīng)為類的職責(zé)變化。如果一個類承擔(dān)了多于一個的職責(zé),那么引起它變化的原因就會有多個。
如果一個類承擔(dān)的職責(zé)過多,就等于把這些職責(zé)耦合在了一起。一個職責(zé)的變化可能會消弱或者抑制這個類完成其他職責(zé)的能力。這種耦合會導(dǎo)致脆弱的設(shè)計,當(dāng)發(fā)生變化時,設(shè)計會遭受到意想不到的破壞。
如下圖的設(shè)計。Rectangle類具有兩個方法,一個方法把矩形繪制在屏幕上,另一個方法計算矩形的面積。
有兩個不同的應(yīng)用程序使用Rectangle類,一個應(yīng)用程序是有關(guān)計算幾何學(xué)方面的,利用Rectangle類計算幾何形狀,但不會在屏幕上繪制矩形。另外一個應(yīng)用程序?qū)嵸|(zhì)上是有關(guān)圖形繪制方面的,它可能也會進(jìn)行一些計算幾何學(xué)方面的工作,但是他肯定會在屏幕上繪制矩形。
這個設(shè)計違反了單一職責(zé)的原則(SRP)。Rectangle類具有兩個職責(zé)。
第一:提供了一個矩形幾何形狀的數(shù)學(xué)模型;
第二:把矩形在一個圖形用戶界面上繪制出來。
導(dǎo)致的問題:
首先,我們必須在計算幾何應(yīng)用程序中包含進(jìn)GUI代碼。在.NET中,就必須要把GUI組建和計算幾何應(yīng)用一起構(gòu)建、部署。
其次,如果GraphicalApplication的改變由于一些原因?qū)е铝薘ectangle的改變,那么這個改變會迫使我們重新構(gòu)建、測試以及部署ComputationalGeometryApplication。如果忘記了這樣做,ComputationalGeometryApplication可能會有不可預(yù)測的問題。
一個較好的設(shè)計是把這兩個職責(zé)分離到下圖中所示的兩個完全不同的類中。
二、定義職責(zé)
在SRP中,我們把職責(zé)定義為變化的原因。如果你能夠想到多于一個的動機去改變一個類,那么這個類就具有多于一個的職責(zé)。
如下代碼中Modem的接口,大都數(shù)人都會認(rèn)為這個接口看起來非常合理。該接口所聲明的4個方法確實是調(diào)制解調(diào)器所具有的功能。
1 2 3 4 5 6 7 | public interface IModem { void Dial( string pno); void Hangup(); void Send( char c); char Recv(); } |
然而,該接口中卻顯示出兩個職責(zé)。第一:鏈接管理;第二:數(shù)據(jù)通信。Dial和Hangup方法進(jìn)行調(diào)制解調(diào)器的鏈接處理,而Send和recv方法進(jìn)行數(shù)據(jù)通信。
這兩個職責(zé)應(yīng)該分開嗎?這依賴于應(yīng)用程序的變化方式。如果應(yīng)用程序的變化會影響到鏈接方法的簽名(signature),那么這個設(shè)計就具有僵化性的臭味,因為調(diào)用Send和Recv的類必須要重新編譯、部署的次數(shù)常常會超過我們希望的次數(shù)。在這種情況下,這兩個職責(zé)應(yīng)該被分離,如下圖。這樣做避免了客戶應(yīng)用程序和這兩個職責(zé)耦合在一起。
另一方面,如果應(yīng)用程序的變化方式總是導(dǎo)致這兩個職責(zé)同時變化,那么就不必分離他們。這時,分離它們就會具有不必要的復(fù)雜性的臭味。
僅當(dāng)變化發(fā)生時,變化的軸線(職責(zé))才具有實際的意義。
我們把兩個職責(zé)都耦合進(jìn)了ModemImplementation類中,這不是所希望的,但或許是必要的,常常由于一些和硬件或者操作系統(tǒng)的細(xì)節(jié)有關(guān)的原因,迫使我們這樣去處理。我們可以把它看做一個有缺陷的類,所有的依賴關(guān)系都是從它出發(fā),誰也不需要依賴它。除了Main以為,誰也不需要知道它的存在。因此我們已經(jīng)把丑陋的部分隱藏起來。
聯(lián)系客服