C#設計模式六大原則 - 接口隔離


接口隔離原則(ISP)

Interface Segregation Principe,簡稱:ISP。

類的依賴關係應建立在最小接口上,不要都塞在一起。即客戶端不應該依賴它不需要的接口。

問題由來:類A通過接口Interface依賴類B,類C通過接口I依賴類D,如果接口Interface對於類A和類B來說不是最小接口,則類B和類D必須去實現他們不需要的方法。

解決方案:將臃腫的接口Interface拆分爲獨立的幾個接口,類A和類C分別與他們需要的接口建立依賴關係。也就是採用接口隔離原則。

接口隔離原則的含義:建立單一接口,不要建立龐大臃腫的接口,儘量細化接口,接口中的方法儘量少。也就是說,我們要爲各個類建立專用的接口,而不要試圖去建立一個很龐大的接口供所有依賴它的類去調用。在程序設計中,依賴幾個專用的接口要比依賴一個綜合的接口更靈活。接口是設計時對外部設定的“契約”,通過分散定義多個接口,可以預防外來變更的擴散,提高系統的靈活性和可維護性。

接口隔離原則就是要求只提供儘可能小的接口,需要高內聚,不需要的行爲要隱藏起來

說到這裏,很多人會覺的接口隔離原則跟之前的單一職責原則很相似,其實不然。

  • 其一,單一職責原則原注重的是職責;而接口隔離原則注重對接口依賴的隔離。
  • 其二,單一職責原則主要是約束類,其次纔是接口和方法,它針對的是程序中的實現和細節;而接口隔離原則主要約束接口,主要針對抽象,針對程序整體框架的構建。

採用接口隔離原則對接口進行約束時,要注意以下幾點:

  • 接口儘量小,但是要有限度。對接口進行細化可以提高程序設計靈活性是不掙的事實,但是如果過小,則會造成接口數量過多,使設計複雜化。所以一定要適度。
  • 爲依賴接口的類定製服務,只暴露給調用的類它需要的方法,它不需要的方法則隱藏起來。只有專注地爲一個模塊提供定製服務,才能建立最小的依賴關係。
  • 提高內聚,減少對外交互。使接口用最少的方法去完成最多的事情。

一、舉個例子

繼續拿手機說事兒吧,ICellphone接口有四個方法,分別爲打電話、發短信、上網、網遊戲。Cellphone繼承接口ICellphone,實現了以上四個方法。
代碼如下:

public Interface ICellphone 
{
	void Call();	//打電話
	void Text();	//發短信
	void Online();	//上網
	void PlayGame();	//玩遊戲
}

public class Cellphone : ICellphone 
{
	public void Call()
    {
        Console.WriteLine("User {0} Call", this.GetType().Name);
    }
    public void Text()
    {
        Console.WriteLine("User {0} Text", this.GetType().Name);
    }
    public void Online()
    {
        Console.WriteLine("User {0} Online", this.GetType().Name);
    }
	public void PlayGame()
    {
        Console.WriteLine("User {0} PlayGame", this.GetType().Name);
    }
}

以上代碼功能完備,很強大,看起來是不是很完美。當然,單從單一職責上考濾是沒有問題的,但仔細想想,從接口隔離原則的角度出發的話,就不同了。 要是柯南拿一款只能打電話發短信的老人機,那上網和玩遊戲功能是不是就封裝過度了。

因此,這裏需要再修改。將 ICellphone 分割成兩個接口 IBaseCellphone 和 IWebCellphone 。
代碼如下:

//手機基礎功能
public Interface IBaseCellphone 
{
	void Call();	//打電話
	void Text();	//發短信
}
//手機上網和遊戲功能
public Interface IWebCellphone 
{
	void Online();		//上網
	void PlayGame();	//玩遊戲
}

public class Cellphone : IBaseCellphone, IWebCellphone 
{
    public void Call()
    {
        Console.WriteLine("打電話");
    }
    public void Text()
    {
        Console.WriteLine("發短信");
    }
    public void Online()
    {
        Console.WriteLine("手機已連網");
    }
    public void PlayGame()
    {
        Console.WriteLine("開始玩遊戲");
    }
}

場景中使用:

/// <summary>
/// 現實生活中的場景,使用手機
/// </summary>
public class People
{
    public int Id { get; set; }
    public string Name { get; set; }

    /// <summary>
    /// 一些人只使用手機的基本功能
    /// </summary>
    /// <param name="phone"></param>
    public void UsePhone(IBaseCellphone cellphone)
    {
        Console.WriteLine("我是 {0},我只用基礎的功能", this.Name);
        cellphone.Call();
        cellphone.Text();
    }

    /// <summary>
    /// 只想上網玩遊戲
    /// </summary>
    /// <param name="cellphone"></param>
    public void PlayOnlineGame(IWebCellphone cellphone)
    {
        Console.WriteLine("我是 {0},我只想上網玩遊戲", this.Name);
        cellphone.Online();
        cellphone.PlayGame();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章