SRP 是 SOLID 原則之首。「職責」定義為「變化的原因」,原則內容:「一個類應有且僅有一個變化的原因」。遵循 SRP 的收益:任何一個變化只影響一個類,降低適應變化的成本,提升系統可維護性。
以 Modem 類為例,擁有撥號、掛斷、發送、接收四個方法:
class Modem {
public void Dial(string pno) { ... }
public void Hangup() { ... }
public void Send(char data) { ... }
public char Receive() { ... }
}
變化點分兩類:
此類同時承擔多個變化原因,違反 SRP。但 Modem 符合現實概念模型,難道要強行拆成四個類?關鍵在於抽象層次。
將低層實現細節抽象為穩定介面,高層類透過組合依賴介面:
interface IDialable { void Dial(string pno); }
class Dialer : IDialable { public void Dial(string pno) { ... } }
class Modem {
private IDialable _dialer;
public void Dial(string pno) { _dialer.Dial(pno); }
// Hangup, Send, Receive 同理組合相應介面
}
現在:
Dialer 只因撥號實現變化而變化(低層)。Modem 只因整體協議/介面變化而變化(高層)。類只有一個變化原因 → 一個變化只影響一個類 → 變化只影響其相應層次的類。
理解 SRP 的關鍵在於識別類的抽象層次:高層類抽象高層概念,低層類抽象低層概念。良好的抽象層次自然滿足 SRP,反之亦然。