首頁 >後端開發 >php教程 >PHP物件導向五大原則之介面隔離原則(ISP)詳解

PHP物件導向五大原則之介面隔離原則(ISP)詳解

不言
不言原創
2018-04-04 17:24:021560瀏覽

這篇文章主要介紹了PHP物件導向介面隔離原則(ISP),詳細分析了介面隔離的概念、原則、使用方法及相關操作注意事項,需要的朋友可以參考下

#本文實例講述了PHP物件導向五大原則之介面隔離原則(ISP)。分享給大家供大家參考,具體如下:

設計應用程式的時候,如果一個模組包含多個子模組,那麼我們應該小心對模組做出抽象。設想這個模組由一個類別實現,我們可以把系統抽象化成一個介面。但是要新增一個新的模組擴充程式時,如果要新增的模組只包含原始系統中的一些子模組,那麼系統就會強迫我們實作介面中的所有方法,並且清寒要編寫一些啞方法。這樣的接口被稱為肚胖接口或被污染的接口,使用這樣的接口將為系統引入一些不當的行為,這些不當的行為可能導致不正確的結果,也可能導入資源浪費。

1.介面隔離

介面隔離原則(Interface Segregation Principle, ISP)表示客戶端不應該強迫實作一些他們不會使用的接口,應該把胖接口中的方法分組,然後用多個接口替代它,每個接口服務於一個子模組。簡單地說,就是使用多個專門的介面比使用單一介面好很多。

ISP的主要觀點如下:

1)一個類別對另一個類別的依賴性應是建立在最小的介面上的。

ISP可以達到不強迫客戶(介面的使用方法)依賴他們不用的方法,介面的實作類別應該只呈現為單一職責的角色(遵循SRP原則)

ISP還可以降低客戶之間的相互影響---當某個客戶要求提供新的職責(需要變化)而迫使介面發生變化時,影響到其他客戶程式的可能性最小。

2)客戶端程式不應該依賴它不需要的介面方法(功能)。

客戶端程式就應該依賴它不需要的介面方法(功能),那要依賴什麼?依賴它所需要的介面。客戶端需要什麼接口就是提供什麼接口,把不需要的接口剔除,這就要求對接口進行細化,保證其純潔性。

例如在繼承時,由於子類別將繼承父類別中的所有可用方法;而父類別中的某些方法,在子類別中可能並不需要。例如,普通員工和經理都繼承自僱員這個接口,員工需要每天寫工作日誌,而經理不需要。因此不能用工作日誌來卡片經理,也就是經理不應該依賴提交工作日誌這個方法。

可以看出,ISP和SRP在概念上是有一定交叉的。事實上,許多設計模式在概念上都有交叉,甚至你很難判斷一段程式碼屬於哪一種設計模式。

ISP強調的是介面對客戶端的承諾越少越好,並且要做到專一。當某個客戶程式的要求發生變化,而迫使介面發生改變時,影響到其他客戶程式的可能性小。這其實就是介面污染的問題。

2.對介面的污染

過於臃腫的介面設計是對介面的污染。所謂的介面污染就是為介面添加不必要的職責,如果開發人員在介面中增加一個新功能的目的只是減少介面實現類別的數目,則此設計將導致介面被不斷地“污染”並“變胖” 。

「介面隔離」其實就是客製化服務設計的原則。使用介面的多重繼承實現對不同的介面的組合,從而對外提供組合功能---達到「按需提供服務」。

介面即要拆,但也不能拆得太細,這就得有個標準,這就是高內聚。介面應該具備一些基本的功能,能獨一完成一個基本的任務。

在實際應用中,會遇到如下問題:比如,我需要一個能適配多種類型資料庫的DAO實現,那麼首先應實現一個資料庫操作的接口,其中規定一些資料庫操作的基本方法,例如連接資料庫、增刪改查、關閉資料庫等。這是一個最少功能的介面。對於某些MySQL中特有的而其他資料庫裡並不存在的或性質不同的方法,如PHP裡可能用到的MySQL的pconnect方法,其他資料庫裡並不存在和這個方法相同的概念,這個方法也就不應該出現在這個基本的介面裡,那這個基本的介面應該有哪些基本的方法呢? PDO已經告訴你了。

PDO是一個抽象的資料庫介面層,它告訴我們一個基本的資料庫操作介面應該實作哪些基本的方法。介面是一個高層次的抽象,所以介面裡的方法都應該是通用的、基本的、不易變化的。

還有一個問題,那些特有的方法該怎麼實現?根據ISP原則,這些方法可以在別一個介面中存在,讓這個「異類」同時實作這兩個介面。

對於介面的污染,可以考慮這兩條處理方式:

利用委託分離介面。

利用多重繼承分離介面。

委託模式中,有兩個物件參與處理同一個請求,接受請求的物件將請求委託給另一個物件來處理,如策略模式、代理模式等都應用到了委託的概念。

再來看實例說明

你有沒有遇到非常「胖」的介面呢?

舉個例子來說吧:有一個跟動物有關的接口,程式碼如下:

<?php
interface Animal{
  public function walk();
  public function speak();
}

狗是這個接口的一個具體實現:

<?php
require_once "animal.php";
class Dog implements Animal{
  public function walk(){
    echo "dogs can walk";
  }
  public function speak(){
    echo "dogs can speak";
  }
}

ok,現在我們想創造一個魚類,它會游泳,怎麼辦呢?我們必須要修改接口,也會影響到dog類別的實現,而fish也需要實作walk和speak方法,如下程式碼所示:

Animal介面類別:

<?php
interface Animal{
  public function walk();
  public function speak();
  public function swim();
}

dog類別:

<?php
require_once "animal.php";
class Dog implements Animal{
  public function walk(){
    echo "dogs can walk";
  }
  public function speak(){
    echo "dogs can speak";
  }
  public function swim(){
  }
}

#fish類別:

<?php
require_once "animal.php";
class Fish implements Animal{
  public function walk(){
  }
  public function speak(){
  }
  public function swim(){
    echo "fish can swim";
  }
}

這時Animal介面類別就呈現出了」胖「介面的特徵了。所謂胖接口其實就是接口中定義了不是所有實現類都需要的方法,就像Animal接口類,有些動物是不會游泳的,有些動物是不會行走的,還有些動物是不會飛的。如果將這些方法都寫在一個Animal介面類別中,那麼後期的擴充和維護簡直就是一場災難。

那麼,要怎麼解決以上問題呢?

很簡單,介面精進即可,將Animal介面類別分割成三個介面類別:

animalCanWalk介面類別:

<?php
interface animalCanSpeak{
  public function speak();
}

AnimalCanSwim介面類別:

<?php
interface AnimalCanSwim{
  public function swim();
}

#animalCanSpeak介面類別:

<?php
interface animalCanSpeak{
  public function speak();
}

定義好這幾個介面類別之後,dog和fish的實作就容易多了,

<?php
require_once "animalCanSpeak.php";
require_once "animalCanWalk.php";
class Dog implements animalCanSpeak,animalCanWalk{
  public function walk(){
    echo "dogs can walk";
  }
  public function speak(){
    echo "dogs can speak";
  }
}

<?php
require_once "animalCanSwim.php";
class Fish implements AnimalCanSwim{
  public function swim(){
    echo "fish can swim";
  }
}

總結一下:

介面隔離原則(Interface  Segregation Principle, ISP)的概念:使用多個專門的接口,而不使用單一的總接口,即客戶端不應該依賴那些它不需要的接口。

在使用介面隔離原則時,我們需要注意控制介面的粒度,介面不能太小,如果太小會導致系統中介面氾濫,不利於維護;介面也不能太大,太大的介面將違反介面隔離原則,彈性較差,使用起來很不方便。一般而言,介面中僅包含為某一類使用者自訂的方法即可,不應該強迫客戶依賴那些它們不用的方法。

相關推薦:

PHP物件導向五大原則之開放-封閉原則(OCP)詳解

以上是PHP物件導向五大原則之介面隔離原則(ISP)詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn