接口隔离原则
在一个视频里看到一个非常好的通过故事情节来描述接口隔离原则的例子,这里使用文字来将其描述一下。
故事开始
情节一、 一对情侣,男孩给女孩买了一辆跑车;女孩报了驾校,准备考驾照。
那么我们先使用程序来定义这辆跑车。跑车属于车里的一个种类,具有跑的属性,那么我们定义一个跑的接口,让跑车来实现这个跑的功能。
- 定义跑的接口:
public interface IVehicle {
void Run ();
}
- 定义跑车类,实现跑的接口:
public class SportsCar : IVehicle {
string name = "跑车";
public void Run () {
Console.WriteLine (name + "-Ruing :" + ">>>>>>>>>>>>");
}
}
- 女孩报名学驾照
public class Driver {
private IVehicle _vehicle;
public Driver (IVehicle vehicle) {
_vehicle = vehicle;
}
public void Drive () {
_vehicle.Run ();
}
}
- 女孩开着跑车上了街
class Program {
static void Main (string[] args) {
var driver=new Driver(new SportsCar());
driver.Drive();
}
}
- 输出如下:
跑车-Ruing :>>>>>>>>>>>>
情节二、 妹子开跑车追尾了,打电话向男主哭诉;男子安慰到,别哭,明儿个哥给你买辆坦克,妹子喜笑颜开。
在程序中定义男主买的坦克,坦克按分量分三种类型,分别是轻型坦克、中型坦克、重型坦克。坦克会跑、能开火。
- 定义跑、开火的接口
public interface ITank {
void Run ();
void Fire ();
}
- 定义轻型坦克类,实现 ITank 接口
public class LightTank : ITank {
string name = "轻型坦克";
public void Fire () {
Console.WriteLine (name + "-Fire :" + ">>>");
}
public void Run () {
Console.WriteLine (name + "-Runing" + ">>>>>>>>>");
}
}
- 定义中型坦克类,实现 ITank 接口
public class MediumTank : ITank {
string name = "中型坦克";
public void Fire () {
Console.WriteLine (name + "-Fire :" + ">>>>>>");
}
public void Run () {
Console.WriteLine (name + "-Runing :" + ">>>>>>");
}
}
- 定义重型坦克,实现 ITank 接口
public class WeightTank : ITank {
string name = "重型坦克";
public void Fire () {
Console.WriteLine (name + "-Fire :" + ">>>>>>>>>");
}
public void Run () {
Console.WriteLine (name + "-Runing :" + ">>>");
}
}
情节三、女孩准备开坦克上街
- 原先学开跑车的驾照,如下:
public class Driver {
private IVehicle _vehicle;
public Driver (IVehicle vehicle) {
_vehicle = vehicle;
}
public void Drive () {
_vehicle.Run ();
}
}
我们发现并不能使用原先的驾照来开坦克。那么回头观察一下我们的 ITank 接口,发现,这个接口不仅定义了 Run方法,而且也定义了Fire方法,妹子总不能上街的时候,开着坦克随意开火吧,所以开火这个功能,妹子是使用不到的。那么,我们就需要把开火这个功能,单独定义一个接口,在需要使用到的类中实现。
- 定义一个实现开火的接口:
public interface IWeapon {
void Fire ();
}
- 改造原先的 ITank 接口, ITank 实现IVehicle,IWeapon 接口
public interface ITank :IVehicle,IWeapon{}
- 这个时候,妹子不用更换驾照,就可以使用原先的驾照来开坦克啦。妹子兴高采烈的开着各种型号的坦克上街。
class Program {
static void Main (string[] args) {
var driver_SportsCar=new Driver(new SportsCar());
var driver_LightTank=new Driver(new LightTank());
var driver_weightTank = new Driver (new WeightTank ());
var driver_MediumTank=new Driver(new MediumTank());
driver_SportsCar.Drive();
driver_LightTank.Drive();
driver_MediumTank.Drive();
driver_weightTank.Drive();
}
}
- 一照在手,天下我有;输出如下:
跑车-Ruing :>>>>>>>>>>>>
轻型坦克-Fire>>>>>>>>>
中型坦克-Runing :>>>>>>
重型坦克-Runing :>>>
情节四、加戏,妹子嫌开坦克不过瘾,要开飞机
- 定于IFly 接口,并继承IVehicle 接口
public interface IFly : IVehicle {
void Fly ();
}
- 实现飞机类
public class AirPlane : IFly {
string name = "飞机";
public void Fly () {
Console.WriteLine (name + "-飞呀 " + ">>>>>>>>>>>>>>>>>>");
}
public void Run () {
Console.WriteLine (name + "轰隆隆:" + ">>>>>>>>>>>>>>>");
}
}
- 妹子开飞机
class Program {
static void Main (string[] args) {
var driver_Airplane = new Driver (new AirPlane ());
driver_Airplane.Drive ();
}
}
输出如下:
飞机轰隆隆:>>>>>>>>>>>>>>>
总结
-
客户端不应该依赖它不需要使用的接口
-
类与类之间的依赖关系应该建立在最小的接口上
-
使用多个专门的接口,而不使用单一的总接口,如上所述,ITank 接口继承自 IVehicle 接口和IWeapon接口,IVehicle和IWeapon 分别实现Run和Fire方法。当妹子开跑车的时候他是不需要开火功能的,即客户端不应该依赖那些它不需要的接口。
更多内容欢迎关注: