Single Responsibility Principle 單一職責原則

從原則的名稱很容易就可以得出該原則需要做的事情——物件只擁有/負責某一個責任。
怎麼樣才是擁有/負責一個責任呢?
🌰(例子):

  • 我們設計某個類別只負責會員的邏輯。
    • 會員可以進行下單的動作,那麼下單邏輯則可以放在該類別中
    • 會員無法刪除他人的評論,那麼刪除他人評論的邏輯,就不可實作在該類別中。
  • 遊戲中設計劍的邏輯:
    • 若是仙劍等玄幻遊戲的話,可能需要加入飛行的能力。
    • 若是其他現實類遊戲的話,可能不需要飛行的能力,就不應該實作在該類別中。
    • 劍可以釋放技能,只是每把劍的技能不同,所以上層類別只需要知道劍能釋放技能,而技能的效果只需要劍自行實作即可。

從上面幾個🌰可以看到,我們需要先定義出某些類別的能力,然後再來實作它。
只要不超出定義的範圍,那麼無論實作多少種類別,對於使用到定義類別的上層類別的影響都不會太大。

網路上看到一句話: program to an interface, not an implement

我們定義好類別的能力,也就是定義出了一個抽象(abstract)/介面(interface)。
每一個不一樣的會員/劍,只要實作它們自己的細節,實際動作的方法,不實作額外的事情,就符合單一職責原則

這個原則其實也能套用到現實世界中也適用喔~

  • 公司找程式人員時,不是找某個類別的人,而是只找有實作程式能力的人。
    • 那麼只需要來應徵的人有自己實現寫程式的介面即可,公司不會理會你有沒有飛行執照,公司注意的是你的寫程式介面。
  • 駕駛車子的方法。
    • 駕駛車子只需要駕駛員有實現駕駛的能力(考到駕照
    • 可能某些殘障人士駕駛的車子需要做一些改裝後,殘障人士才能駕駛,那麼這時候“駕駛”這個介面就需要定義2種。

依照該原則實作程式的特點有:

  • 各個類別的責任/邏輯解耦(decoupling)。
  • 類別只負責自己的實作,只要其定義沒有修改,就不需要修改實作,穩定性UP。
  • 每個類別有自己的邏輯/責任,修改其他類別後,類別間的影響不大,穩定性UP UP。

程式範例

參考: https://github.com/exia56/player-training2
該程式只是模擬個簡單的開發流程,以及簡單的程式碼。

在我寫的參考程式中,我只有基本定義2個介面——player與playlist。

1
2
3
4
5
6
7
8
9
//~/modal/player/iPlayer.cs
interface iPlayer
{
void initPlayer(string path);
void play();
void pause();
void stop();
void dispose();
}

我定義了player可以播放、暫停、停止、初始化等。
只要player的定義不更改,那麼實作player介面的類別都不需要修改。
對於上層類別(Program),他只需要知道我們使用的類別一定會實作IPlayer介面就好,內容實作了什麼程式都不重要(VLC or WMP)。

1
2
3
4
5
// ~/modal/playlistEnumerable.cs
interface iPlaylistEnumerable
{
string getNext();
}

playlist的部分則是只定義了取得下一個播放文件的功能。
我們也可以在接下來的版本定義playlist的功能有增加影片、修改播放順序、刪除影片等功能。(小夥伴們可以自己想想能怎麼做吧~

Program類別使用到了player與playlist介面,那麼相對來說:

  • Program相對於player與playlist是上層類別。
  • player與playlist相對於Program是下層類別。

Program作為上層類別,只需要知道各個介面的能力即可,不需要知道實作介面的類別的細節。
而下層類別的player與playlist則只需要處理好自己以及自己的下層類別就好了~

總結

我們定義好類別的能力,也就是定義出了一個抽象(abstract)/介面(interface),再來以該抽象/介面來實作就好了喔。

話說。。。介紹完這個原則後,我發現SOLID的東西其實已經解釋了7成了,剩下的只是沒有說清楚講明白而已。
接下來幾篇文章就再繼續補充好了,反正總結起來,就是下面這句話的體現了。

program to an interface, not an implement

知識鏈結

搞笑談工程: http://teddy-chen-tw.blogspot.com/2014/04/solid.html