文章目录
- 单一职责原则(Single Reponsibility Principle,SRP)
- 里氏替换原则(Liskov Substitution Principle,LSP)
- 依赖倒置原则(Dependence Inversion Principle,DIP)
- 接口隔离原则(Interface Segregation Principe,ISP)
- 迪米特法则(Law of Demeter,LOD)
- 开闭原则(Open Closed Principle,OCP)
接口隔离原则(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();
}
}