首頁 » 物件導向 » [SOLID原則(四)] 介面隔離原則(ISP)

[SOLID原則(四)] 介面隔離原則(ISP)

作者:

分類:

甚麼是SOLID?

SOLID,是由Robert C. Martin等人提出的5個物件導向設計原則的英文字首組成,分別為單一職責(S)開閉原則(O)里氏替換(L)、介面隔離(I)以及依賴反轉(D)。SOLID提供程式開發者良好的設計指引,可以開發出易理解、易維護、易拓展的系統。

介面隔離原則(Interface Segregation Principle,ISP)

Interface Segregation Principle,ISP

No client should be forced to depend on methods it does not use.

譯文:「使用者(client)不應該擁有其用不到的功能。」

字面上大意是使用者在運用這物件時,只會看到他需要的功能。

介面跟繼承最大的不同是,繼承需要從底層一路實作上來,加上不建議用多重繼承的情況下,這時使用介面的優勢就出現了。介面會比較像是組合積木,把需要的不同功能加到類別上,然後實作相對應的功能。

介面隔離原則在系統界接時很常會看到,例如UI綁定、系統元件之間的隔離,或是系統與外部元件及進一步衍伸出的依賴反轉原則。

舉例

假設有組系統參數內有相機、手臂、伺服馬達這些參數,但不希望在取得相機的參數時候也看的到其他元件的參數,因此把參數拆了三個介面分別代表不同的參數集。

interface ICameraParams
{
    int ExposureTime { get; set; }
}

interface IRobotParams
{
    int PlaySpeed { get; set; }
}

interface IServoParams
{
    int GearRatio { get; set; }
}

如果機台分兩站,站點A有手臂、伺服控制,我只需要掛上兩個介面。站點B多了相機就再多掛一個相機介面即可。

class SystemParamsA : IRobotParams, IServoParams
{
    public int PlaySpeed { get; set; }
    public int GearRatio { get; set; }
}

class SystemParamsB : ICameraParams, IRobotParams, IServoParams
{
    public int ExposureTime { get; set; }
    public int PlaySpeed { get; set; }
    public int GearRatio { get; set; }
}

使用時,使用介面會比直接使用實作的物件來的容易理解,只要使用介面去接對應的物件,這實就不會看到介面以外的屬性。

在UI實作上也是相同操作,把相機UI綁ICameraParams,只要是有掛上ICameraParams的物件都可以載入並顯示。

SystemParamsA sp = new SystemParamsA();
ICameraParams camera = sp;
camera.ExposureTime = 100;
List<IRobotParams> robots = new List<IRobotParams>();
robots.Add(new SystemParamsA());
robots.Add(new SystemParamsB());

foreach(var item in robots)
{
    item.PlaySpeed = 100;
}

結論

介面的玩法很多,而且可以做到比繼承來的靈活。這不是說介面可以取代繼承,而是兩個完全不同的用途。繼承就像是在蓋房子,必須從打地基開始一路蓋上去;介面就像在選配件裝潢,要蓋房間、廚房、陽台之類的,或是看到別人家裝潢好看,只需要把他的介面掛到我家就可以了。

題外話,自己初學時會有點分不出這兩者個差異,隨著經驗的累積,以及學習Design Pattern、SOLID…等觀念,已經能大致判斷哪些狀況下要使用繼承或是介面了。

參考資料

「cian」的個人頭像

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *