4.接口隔離原則(Interface Segregation Principle)


1.定義

      客戶端不應該依賴它不需要的接口;

     一個類對另一個類的依賴應該建立在最小的接口上。

2.定義解讀

     定義包含三層含義:

  • 一個類對另一個類的依賴應該建立在最小的接口上;
  • 一個接口代表一個角色,不應該將不同的角色都交給一個接口,因為這樣可能會形成一個臃腫的大接口;
  • 不應該強迫客戶依賴它們從來不用的方法。

     接口隔離原則有點像單一職責原則,但是也有區別,在單一職責原則中,一個接口可能有多個方法,提供給多種不同的調用者所調用,但是它們始終完成同一種功能,因此它們符合單一職責原則,卻不符合接口隔離原則,因為這個接口存在着多種角色,因此可以拆分成更多的子接口,以供不同的調用者所調用。比如說,項目中我們通常有一個Web服務管理的類,接口定義中,我們可能會將所有模塊的數據調用方法都在接口中進行定義,因為它們都完成的是同一種功能:和服務器進行數據交互;但是對於具體的業務功能模塊來說,其他模塊的數據調用方法它們從來不會使用,因此不符合接口隔離原則。

3.優點

     使用接口隔離原則,意在設計一個短而小的接口和類,符合我們常說的高內聚低耦合的設計思想,從而使得類具有很好的可讀性、可擴展性和可維護性。

4.問題提出

     類A通過接口I依賴類B,類C通過接口I依賴類D,如果接口I對於類A和類C來說不是最小接口,而類B和類D必須去實現它們不需要的方法。下面通過一個UML圖來說明這種現象:

     在這里,我們定義了一個動物活動的接口IAnimal,里面有4個方法:飛行fly、行走walk、吃eat和工作work,然后分別用人類People和鳥類Bird實現了這個接口。中國人類ChinesePeople和鸚鵡類Parrot通過接口IAnimal分別依賴類People和類Bird。很明顯,對於ChinesePeople來說,fly方法是多余的,因為人不會飛;對於Parrot類來說,work方法是多余的,因為鸚鵡不需要工作。接口IAnimal對於類ChinesePeople和類Parrot來說不是最小接口。

5.解決方案

     將臃腫的接口IAnimal拆分為獨立的幾個接口,類ChinesePeople和類Parrot分別與它們需要的接口建立依賴關系,也就是采用接口隔離原則。修改后的UML圖如下所示:

 

6.示例

import Foundation

@objc protocol IAnimal
{
    optional func walk();
    func eat();
}

protocol IPeople
{
    func work();
}

protocol IBird
{
    func fly();
}

class People: NSObject, IAnimal, IPeople
{
    func walk()
    {
        print("People walk");
    }
    
    func eat()
    {
        print("People eat");
    }
    
    func work()
    {
        print("People work");
    }
}

class Bird: NSObject, IAnimal, IBird
{
    func eat()
    {
        print("Bird eat");
    }
    
    func fly()
    {
        print("Bird Fly");
    }
}

class ChinesePeople
{
    var chinesePeople: protocol<IAnimal, IPeople>?;
    
    func peopleWalk()
    {
        chinesePeople?.walk!();
    }
    
    func peopleEat()
    {
        chinesePeople?.eat();
    }
    
    func peopleWork()
    {
        chinesePeople?.work();
    }
}

class Parrot
{
    var parrot: protocol<IAnimal, IBird>?;
    
    func parrotEat()
    {
        parrot?.eat();
    }
    
    func parrotFly()
    {
        parrot?.fly();
    }
}

let chinesePeople = ChinesePeople();
chinesePeople.chinesePeople = People();
chinesePeople.peopleEat();  //打印:People eat

let parrot = Parrot();
parrot.parrot = Bird();
parrot.parrotEat();  //打印:Bird eat

     說明:從UML圖可以看到,遵守接口隔離原則,會使代碼量增加不少,源碼中也是這樣;實際上,IOS在定義協議的時候,可以設置方法為可選實現(optional)和必須實現(默認值),我們可以設置work方法和fly方法為可選實現的方法,這樣在類People和類Bird中,這兩個方法可以根據需要來決定是否實現。采用這種方式,功能上實現是沒有問題,對於簡單的接口來說,也便於維護和管理。但是,當方法隨着業務需求的增加而不斷增加的話,如果我們不應用接口隔離原則,那么就可能形成一個龐大臃腫的接口,這樣的接口的可維護性和重用性是很差的。因此,我們應該盡量細化接口,本篇將一個接口變更為3個專用的接口所采用的就是接口隔離原則。在項目開發中,依賴幾個專用的接口要比依賴一個綜合的接口更加靈活。通過分散定義多個接口,可以預防外來變更的擴散,提高系統的靈活性和可維護性。

     雖然接口隔離原則很有意義,但在實際項目中,應該注意度的把握,接口設計的過大或過小都不好,應該根據實際情況多思考再進行設計。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM