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();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章