Single Resonsibility Principle
動機
在本文中, 職責是指進行一次改變的動機。SRP 規(guī)定如果我們有2個理由去修改一個類,那么我們應該將功能拆分到兩個類中。每個類只承擔一個職責,并且日后如果我們需要進行一個改動,我們就去負責相應職責的類中完成改動。當我們在承擔多項職責的類中做改動時,就可能會影響到類中其他職責所關聯(lián)的功能。
單一職責原則是一個簡單直觀的原則,不過在實踐過程中有時卻很難做好。
目的
一個類應該有且僅有一個改變的理由。
例子
假設我們需要一個對象來持有郵件消息。以下例子我們將使用 IEmail
接口。初看起來一切正常。再仔細看看的話我們可以發(fā)現(xiàn) IEmail
接口和 Email
類擁有2個職責(改變的理由)。 一個是該類在一些郵件協(xié)議中的應用,如 pop3 或 imap。 如果必須支持其他協(xié)議,實例對象就要通過其他方式序列化,同時要增加代碼來支持新的協(xié)議。另一個職責則是針對于郵件內(nèi)容的。即使內(nèi)容是字符串,我們以后可能要支持 HTML 或其他格式。
如果我們僅僅保留一個類,每次對其中一個職責的改變都可能影響到另一個。
- 增加新協(xié)議需要增加代碼來解析和序列化各種字段類型
- 增加新的內(nèi)容格式(如 html )需要我們?yōu)閼玫拿總€協(xié)議增加代碼
// SRP -- Bad Example
interface IEmail{
public void setSender(String sender);
public void setReceiver(String receiver);
public void setContent(String content);
}
class Email implements IEmail{
public void setSender(String sender) {}
public void setReceiver(String receiver) {}
public void setContent(String content) {}
}
我們可以新建一個接口 IContent
和類 Content
來拆分職責。每個類僅有一個職責讓我們的設計更加靈活:
- 增加新協(xié)議只引起
Email
類的改變 - 增加新內(nèi)容類型只引起
Content
類的改變
// SRP -- Good Example
interface IEmail{
public void setSender(String sender);
public void setReceiver(String receiver);
public void setContent(IContent content);
}
interface IContent{
public String getAsString(); // used for serialization
}
class Email implements IEmail{
public void setSender(String sender) {}
public void setReceiver(String receiver) {}
public void setContent(IContent content) {}
}
總結
在軟件應用的設計階段單一職責原則是一種識別類的好方式。它也提醒你思考類可能發(fā)展的各種方向。只有在對應用該如何運行有清晰的全局認識之后,你才能將職責分離做好。
上一篇: 接口隔離原則
下一篇:里氏替換原則
目錄: http://www.lxweimin.com/p/af861220a6cc