設計模式-----單一職責原則

單一職責原則

定義

單一職責原則(Single Responsibility Principle, SRP)是Bob大叔提倡的S.O.L.I.D五大設計原則中的第一個。其中,職責(Responsibility)被表述爲「變化的緣由」(reason to change);SRP被表述爲「一個類應該有且只有一個變化的緣由」。但若是光從字面去理解,SRP很容易讓人望文生義產生誤解。本文但願能闡明SRP的本質,達到避免誤解和指導設計的目的。

動機

對於設計原則的理解應該首先從它的動機入手,即遵循這個原則帶來的好處是什麼?對於SRP來說,若是遵循「一個類應該有且只有一個變化的緣由」是因,那麼「任何一個變化只會影響一個類」就是果。可見SRP的動機主要是系統的可維護性,即下降適應變化的成本。 java

多功能與單變化

對於單功能的類來說,比較容易遵循SRP,好比:把string轉換爲DateTime類型的工具類。理解SRP的難點在於在多功能類的情形,即不容易理解多功能與單變化的矛盾。讓咱們先來看一個Modem類的例子,Modem具備4個功能:撥號,掛斷,發送數據,接收數據: 工具

class Modem {

    public void Dial(string aPno) {…}

    public void Hangup() {…}

    public void Send(char aData) {…}

    public char Receive() {…}

}

咱們先來考察一下Modem類的變化點,並將其分爲兩類:1.Modem類的內部細節變化,好比Dial、Hangup、Send、Receive等具體實現發生了變化;2.Modem類總體性的變化,好比Modem類須要增長Poweron和Poweroff方法。上面的Modem類具備多個變化點,不符合SRP。 設計

抽象與抽象層次

咱們先來考察一下Modem類的變化點,並將其分爲兩類:1.Modem類的內部細節變化,好比Dial、Hangup、Send、Receive等具體實現發生了變化;2.Modem類總體性的變化,好比Modem類須要增長Poweron和Poweroff方法。上面的Modem類具備多個變化點,不符合SRP。 code

interface IDialable{

    void Dial(string aPno);

}

class Dialer : IDialable{

    public void Dial(string aPno){…}

}

  

class Modem{

    public void Dial(string aPno) { m_dialer.Dial(aPno); }

    private IDialable m_dialer;

  

    … //hangup, send, receive相似

}

上面的設計將各個功能點抽象爲單一的接口,將變化封裝在穩定的接口背後,再經過組合的方式創建起總體的Modem類與局部的功能點的聯繫。這樣就避免了低層的變化傳導到高層。 接口

總結

可見,理解SRP的關鍵在於理解類的抽象層次,高層次的類是高層概念的抽象,低層次的類是低層概念的抽象。低層的變化隻影響低層類,高層的變化隻影響高層類。對於遵照SRP的設計,必定具備很好的抽象層次,所以不妨以SRP爲指導和檢驗,幫助咱們設計出好的類來。最後,我用幾個關鍵詞梳理SRP的脈絡:ip

類只有一個變化的緣由 >> 一個變化隻影響一個類 >> 變化隻影響其相應層次的類ci

相關文章
相關標籤/搜索