用 PHP 簡單介紹 SOLID 原則裡面的 I
此為 SOLID 原則介紹的系列文章之一,所有文章的連結如下。
- 用 TypeScript 解釋 SOLID 原則裡的 S
- 用 PHP 解釋 SOLID 原則裡的 O
- 用 TypeScript 簡單介紹 SOLID 原則裡面的 L
- 用 PHP 簡單介紹 SOLID 原則裡面的 I
- 用 TypeScript 簡單介紹 SOLID 原則裡面的 D
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)
{
// ...
}
}
與其他原則一樣,不建議過度使用這條原則,進一步劃分已經非常具體的介面,導致創建的介面越多,程式碼就會越複雜,因此要保持平衡。