面向對象基本原則(1)- 單一職責原則與接口隔離原則

面向對象基本原則(1)- 單一職責原則與接口隔離原則

面向對象基本原則(1)- 單一職責原則與接口隔離原則
面向對象基本原則(2)- 裏式代換原則與依賴倒置原則
面向對象基本原則(3)- 最少知道原則與開閉原則php


1、單一職責原則

1. 單一職責原則簡介

單一職責原則的英文名稱是 Single Responsibility Principle,簡稱SRP。
單一職責原則的原話解釋是:segmentfault

There should never be more than one reason for a class to change.

意思是:應該有且僅有一個緣由引發類的變動。設計模式

2. 單一職責原則優勢

  • 類的複雜性下降,實現什麼職責都有清晰明確的定義。
  • 可讀性提升,複雜性下降,那固然可讀性提升了。
  • 可維護性提升,可讀性提升,那固然更容易維護了。
  • 變動引發的風險下降,變動是必不可少的,若是接口的單一職責作得好,一個接口修改只對相應的實現類有影響,對其餘的接口無影響,這對系統的擴展性、維護性都有很是大的幫助。

3. 最佳實踐

接口必定要作到單一職責,類的設計儘可能作到只有一個緣由引發變化。設計

注意 單一職責原則提出了一個編寫程序的標準,用「職責」或「變化緣由」來衡量接口或類設計得是否優良,可是「職責」和「變化緣由」都是不可度量的,因項目而異,因環境而異。

4. Show me the code

代碼使用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);

2、接口隔離原則

1. 接口隔離原則簡介

接口隔離原則的英文名稱是 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個方法都放在一個接口中,而且提供給多個模塊訪問,各個模塊按照規定的權限來訪問,在系統外經過文檔約束「不使用的方法不要訪問」,按照單一職責原則是容許的,按照接口隔離原則是不容許的,由於它要求「儘可能使用多個專門的接口」。專門的接口就是指提供給每一個模塊的都應該是單一接口,而不是創建一個龐大的臃腫的接口,容納全部的客戶端訪問。開發

2. 接口隔離原則的規範

接口要儘可能小

這是接口隔離原則的核心定義,不出現臃腫的接口(Fat Interface)。
可是「小」是有限度的,根據接口隔離原則拆分接口時,首先必須知足單一職責原則。

接口要高內聚

高內聚就是提升接口、類、模塊的處理能力,減小對外的交互。
具體到接口隔離原則就是,要求在接口中儘可能少使用public方法,接口是對外的承諾,承諾越少對系統的開發越有利,變動的風險也就越少,同時也有利於下降成本。

接口只提供訪問者須要的方法

接口設計要適度

接口的設計粒度越小,系統越靈活,這是不爭的事實。可是,靈活的同時也帶來告終構的複雜化,開發難度增長,可維護性下降,這不是一個項目或產品所指望看到的,因此接口設計必定要注意適度。

3. 最佳實踐

接口隔離原則是對接口的定義,同時也是對類的定義,接口和類儘可能使用原子接口或原子類來組裝。關於原子該怎麼劃分,在實踐中能夠根據如下幾個規則來衡量:

  • 一個接口只服務於一個子模塊或業務邏輯;
  • 經過業務邏輯壓縮接口中的public方法,接口時常去回顧,儘可能讓接口達到「滿身筋骨肉」,而不是「肥嘟嘟」的一大堆方法;
  • 已經被污染了的接口,儘可能去修改,若變動的風險較大,則採用適配器模式進行轉化處理;
  • 每一個項目或產品都有特定的環境因素,環境不一樣,接口拆分的標準就不一樣。深刻了解業務邏輯,根據經驗和常識決定接口的粒度大小。接口粒度過小,致使接口數據劇增,開發人員嗆死在接口的海洋裏;接口粒度太大,靈活性下降,沒法提供定製服務,給總體項目帶來沒法預料的風險

參考文獻:《設計模式之禪》
相關文章
相關標籤/搜索