用 PHP 簡單介紹 SOLID 原則裡面的 I

此為 SOLID 原則介紹的系列文章之一,所有文章的連結如下。

SOLID 原則中的 I


介面隔離原則 (Interface-segregation principles),也就是 SOLID 原則裡面的 I,原文說明如下。

A client should not be forced to implement an interface that it doesn't use.
客戶端不應被迫去使用對其而言無用的方法或是功能。

介面隔離原則 (ISP) 建議應該將龐大臃腫的介面拆分成更小且更具體的介面,讓客戶端 (Client) 只需要實作它們真正需要的方法或功能,這種縮小的介面也被稱為角色介面 (role interfaces)。

介面隔離原則的目的是降低耦合,讓程式碼更容易修改與重構。

舉個簡單的 🌰,假設在我們的程式中,有一個定義雲服務提供商的介面 CloudProvider,此介面的實作有兩個類別。

  • 鼎鼎大名的 AWS
  • 某間我們虛構的,一個剛起步的雲服務提供商
<?php

interface CloudProvider
{
    public function storeFile(string $name);
    public function getFile(string $name);
    public function createServer(string $region);
    public function listServer(string $region);
    public function getCdnAddress();
}

// 鼎鼎大名的 AWS
class AmazonWebServices implements CloudProvider
{
    public function storeFile(string $name)
    {
        // ...
    }

    public function getFile(string $name)
    {
        // ...
    }

    public function createServer(string $region)
    {
        // ...
    }

    public function listServer(string $region)
    {
        // ...
    }

    public function getCdnAddress()
    {
        // ...
    }
}

// 某間新的雲端服務提供商
class SomeNewCloudService implements CloudProvider
{
    public function storeFile(string $name)
    {
        // ...
    }

    public function getFile(string $name)
    {
        // ...
    }

    // 未提供此服務
    public function createServer(string $region)
    {
        // Do nothing
    }

    // 未提供此服務
    public function listServer(string $region)
    {
        // Do nothing
    }

    // 未提供此服務
    public function getCdnAddress()
    {
        // Do nothing
    }
}

由於新的雲端服務提供商才剛起步,部分功能尚未提供,因此 SomeNewCloudService 還無法實作 CloudProvider 介面中的部分方法。因此上述程式碼違反了介面隔離原則。

將上述程式碼進行調整,我們將 CloudProvider 拆分成功能更細微也更具體的小介面。

<?php

interface CloudHostingProvider
{
    public function createServer(string $region);
    public function listServer(string $region);
}

interface CdnProvider
{
    public function getCdnAddress();
}

interface CloudStorageProvider
{
    public function storeFile(string $name);
    public function getFile(string $name);
}

// 大名鼎鼎的 AWS
class AmazonWebServices implements CloudHostingProvider, CdnProvider, CloudStorageProvider
{
    // ...
}

// 某間新雲端服務
class SomeNewWebService implements CloudStorageProvider
{
    public function storeFile(string $name)
    {
        // ...
    }

    public function getFile(string $name)
    {
        // ...
    }
}

與其他原則一樣,不建議過度使用這條原則,進一步劃分已經非常具體的介面,導致創建的介面越多,程式碼就會越複雜,因此要保持平衡。

參考資料


sharkHead
written by
sharkHead

後端工程師, PHP 基金會每月 5 鎂小額贊助人 稍微擅長 PHP、Python 與 Google Search,偶爾寫寫 TypeScript 對於逗號後面必須加空格有著絕對的堅持