面向對象基本原則(1)- 單一職責原則與接口隔離原則
面向對象基本原則(2)- 裏式代換原則與依賴倒置原則
面向對象基本原則(3)- 最少知道原則與開閉原則php
單一職責原則的英文名稱是 Single Responsibility Principle,簡稱SRP。
單一職責原則的原話解釋是:segmentfault
There should never be more than one reason for a class to change.
意思是:應該有且僅有一個緣由引發類的變動。設計模式
接口必定要作到單一職責,類的設計儘可能作到只有一個緣由引發變化。設計
注意 單一職責原則提出了一個編寫程序的標準,用「職責」或「變化緣由」來衡量接口或類設計得是否優良,可是「職責」和「變化緣由」都是不可度量的,因項目而異,因環境而異。
代碼使用PHP7.2語法編寫
IUserBo 接口負責用戶屬性code
interface IUserBo { public function setUserID(string $userID); public function getUserID() : string ; public function setPassword(string $password); public function getPassword() : string ; public function setUserName(string $userName); public function getUserName() : string ; }
IUserBiz 接口負責用戶行爲對象
interface IUserBiz { public function changePassword(string $password) : bool ; public function deleteUser(IUserBo $userBo) : bool ; public function mapUser(IUserBo $userBo); public function addOrg(IUserBo $userBo, int $orgID) : bool; /** * 給用戶添加角色 * @param IUserBo $userBo * @param int $roleID * @return bool */ public function addRole(IUserBo $userBo, int $roleID) : bool ; }
UserInfo 類實現 IUserBo, IUserBiz 兩個接口接口
class UserInfo implements IUserBo, IUserBiz { public function setUserID(string $userID) { // TODO: Implement setUserID() method. } public function getUserID(): string { // TODO: Implement getUserID() method. } public function setPassword(string $password) { // TODO: Implement setPassword() method. } public function getPassword(): string { // TODO: Implement getPassword() method. } public function setUserName(string $userName) { // TODO: Implement setUserName() method. } public function getUserName(): string { // TODO: Implement getUserName() method. } public function changePassword(string $password): bool { // TODO: Implement changePassword() method. } public function deleteUser(IUserBo $userBo): bool { // TODO: Implement deleteUser() method. } public function mapUser(IUserBo $userBo) { // TODO: Implement mapUser() method. } public function addOrg(IUserBo $userBo, int $orgID): bool { // TODO: Implement addOrg() method. } public function addRole(IUserBo $userBo, int $roleID): bool { // TODO: Implement addRole() method. } }
$userInfo = new UserInfo(); // 賦值,就認爲它是一個純粹的屬性 $userInfo->setPassword("abc"); // 執行動做,就認爲是一個業務邏輯類 $userInfo->deleteUser($userInfo);
接口隔離原則的英文名稱是 Interface Segregation Principle,簡稱ISP。
接口隔離原則的英文定義有兩種:ip
Clients should not be forced to depend upon interfaces that they don't use. 客戶端不該該被迫依賴於他們不使用的接口。 The dependency of one class to another one should depend on the smallest possible interface. 類間的依賴關係應該創建在儘量小的接口上。
咱們能夠把這兩個定義歸納爲一句話:創建單一接口,不要創建臃腫龐大的接口。
再通俗一點講:接口儘可能細化,同時接口中的方法儘可能少。ci
接口隔離原則與單一職責的審視角度是不相同的。
單一職責要求的是類和接口職責單一,注重的是職責,這是業務邏輯上的劃分,而接口隔離原則要求接口的方法儘可能少。
例如一個接口的職責可能包含10個方法,這10個方法都放在一個接口中,而且提供給多個模塊訪問,各個模塊按照規定的權限來訪問,在系統外經過文檔約束「不使用的方法不要訪問」,按照單一職責原則是容許的,按照接口隔離原則是不容許的,由於它要求「儘可能使用多個專門的接口」。專門的接口就是指提供給每一個模塊的都應該是單一接口,而不是創建一個龐大的臃腫的接口,容納全部的客戶端訪問。開發
這是接口隔離原則的核心定義,不出現臃腫的接口(Fat Interface)。
可是「小」是有限度的,根據接口隔離原則拆分接口時,首先必須知足單一職責原則。
高內聚就是提升接口、類、模塊的處理能力,減小對外的交互。
具體到接口隔離原則就是,要求在接口中儘可能少使用public方法,接口是對外的承諾,承諾越少對系統的開發越有利,變動的風險也就越少,同時也有利於下降成本。
接口的設計粒度越小,系統越靈活,這是不爭的事實。可是,靈活的同時也帶來告終構的複雜化,開發難度增長,可維護性下降,這不是一個項目或產品所指望看到的,因此接口設計必定要注意適度。
接口隔離原則是對接口的定義,同時也是對類的定義,接口和類儘可能使用原子接口或原子類來組裝。關於原子該怎麼劃分,在實踐中能夠根據如下幾個規則來衡量:
參考文獻:《設計模式之禪》