ISP = Interface Segregation Principle
 
ISP的定义如下:
1、客户端不应该依赖他不需要的接口
2、一个类对另外一个类的依赖性应该是建立在最小的接口上
3、不应当将不同的接口合并在一起,形成一个臃肿的大接口,这是对接口的污染
4、使用多个专门的接口要比使用单一的总接口要好
 
 
ISP的几个使用原则
1、根据接口隔离原则拆分接口时,首先必须满足单一职责原则: 没有哪个设计可以十全十美的考虑到所有的设计原则,有些设计原则之间就可能出现冲突,就如同单一职责原则和接口隔离原则,一个考虑的是接口的职责的单一性,一个考虑的是方法设计的专业性(尽可能的少),必然是会出现冲突。在出现冲突时,尽量以单一职责为主,当然这也要考虑具体的情况。
2、提高高内聚: 提高接口,类,模块的处理能力,减少对外的交互。比如你给杀手提交了一个订单,要求他在一周之内杀一个人,一周后杀手完成了任务,这种不讲条件完成任务的表现就是高内聚。具体来说就是:要求在接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险就越小,也有利于降低成本。
3、定制服务: 单独为一个个体提供优良服务(只提供访问者需要的方法)。
4、接口设计要有限度: 根据经验判断
 
 
接口隔离原则和单一职责原则就是一个硬币的两面,他们说的其实是一回事。
只是接口隔离原则是站在服务调用者角度看问题,单一职责原则是站在服务提供者的角度看。
 
 
===========================================================================================
契约是怎么回事呢?
契约就是在说两件事,甲方在契约里说我不会多要,乙方会在契约里说我不会少给。
乙方的不会少给是比较容易做到的,因为当一个类实现一个接口的时候,他必须要实现接口里的所有方法。如果你不想实现所有的方法,你留下了抽象方法,那你这个类就是抽象类,不能被实例化,即你不是一个完整的服务提供者。所以说乙方不会少给,是强制性的。
甲方不会多要是软性的规定,他是个设计上的东西,需要我们用一些设计原则去约束和控制大家写代码。因为编译器是能检测出乙方是不是少给,没法检查出来甲方是不是多要了。
 
那么我怎么知道甲方有没有多要呢?很简单,就看传递给调用者接口类型里,有没有一直没有被调用到的函数成员,如果有,就说明传递进来的接口类型太大了(太胖了),换句话说 胖接口就是这个接口是由两个或两个以上本质不同的小一点接口合并起来的,把大接口传递进来,只能一部分接口被调用到,另一部分就多余出来了。
根据胖接口的产生原因不同,违反接口隔离原则可能带来的不好的后果基本上有两个:
1、第一种情况,设计的时候有问题,把太多的功能接口包含进来,那其中必然有一部分功能永远用不到,也就自然违反了接口隔离原则。
  我们看一下实例:
   场景介绍: 一对小情侣,一天女生给男生打电话,告诉他车被追尾了,哭的梨花带雨。小男生情商高,哄小女生说 不要紧,明天给你买辆坦克,就不怕追尾了。(前提是小女生不能开炮,只能开~~~~)
 
 
   第一版的实现=》小女生只会开汽车,不会开别的

#region 车辆接口和实现

    interface IVehicle
{
void Run();
} class Car : IVehicle
{
public void Run()
{
Console.WriteLine("Car is Running");
}
}
class Truck : IVehicle
{
public void Run()
{
Console.WriteLine("Truck is Running");
}
} #endregion

驾驶员类:

class Driver
{
private IVehicle _vehicle;
public Driver(IVehicle vehicle)
{
_vehicle = vehicle;
}
public void Drive()
{
_vehicle.Run();
}
}

服务调用方:

   var driver = new Driver(new Car());//开汽车
driver = new Driver(new Truck());//开卡车
driver.Drive(); //这时候你会发现,如果小女生想要开坦克的话,目前是满足不了的
//因为Driver构造参数传递的是IVehicle接口,不是ITank接口
//如果想要满足小女生开坦克上街的愿望,就必须改造Driver,传递ITank接口,请看下一个例子 Console.ReadKey();

第二版的实现=》小女生能开坦克,但是却不能开汽车了

 class Driver
{
private ITank _tank;
public Driver(ITank tank)
{
_tank = tank;
}
public void Drive()
{
_tank.Run();
}
}
   var driver = new Driver(new HeavyTank());//开坦克
driver.Drive(); // 这时候你会发现, 小女生能开坦克上街了,但是你又会发现,小女生现在只会开坦克了,不会开车了
// 问题出现在哪里呢?
// 我们把一个胖接口(ITank)传递进来,这个胖接口中有一个我们永远用不到的功能,就是fire。
// 所以现在这个设计是违反了接口隔离原则
// 具体改造请看下一个例子 Console.ReadKey();
   第三版的实现=》符合接口隔离原则,小女生能开坦克,也能开汽车了。
#region 车辆接口和实现

    interface IVehicle
{
void Run();
} class Car : IVehicle
{
public void Run()
{
Console.WriteLine("Car is Running");
}
}
class Truck : IVehicle
{
public void Run()
{
Console.WriteLine("Truck is Running");
}
} #endregion
interface IWeapon
{
void Fire();
}
  interface ITank:IVehicle,IWeapon
{
}
class LightTank : ITank
{
public void Fire()
{
Console.WriteLine("Boom!");
} public void Run()
{
Console.WriteLine("Ka Ka Ka!");
}
} class HeavyTank : ITank
{
public void Fire()
{
Console.WriteLine("Boom!!!!!!!!");
} public void Run()
{
Console.WriteLine("Ka!!! Ka!!!! Ka!!!!!!");
}
}

驾驶员类:

  class Driver
{
private IVehicle _vehicle;
public Driver(IVehicle vehicle)
{
_vehicle = vehicle;
}
public void Drive()
{
_vehicle.Run();
}
}

服务调用方:

      //接口隔离的原则是 服务的调用方不会都要
//本例子中服务的调用方的需求很简单,这是要求会run,不要求fire
//因此原先的ITank接口中自己包含的fire和run就符合胖接口的规则,他提供了多余的接口给调用方
//因此把ITank接口隔离开是对的
var driver = new Driver(new HeavyTank());//开坦克
driver.Drive();
driver = new Driver(new Car());//开汽车
driver.Drive(); Console.ReadKey();

 第二种情况明天继续,哇哈哈~~~~~~~~~~
 

面向对象的六大原则之 接口隔离原则——ISP的更多相关文章

  1. 设计原则:接口隔离原则(ISP)

    接口隔离原则的英文是Interface Segregation Principle,缩写就是ISP.与里氏替换原则一样其定义同样有两种 定义1: Clients should not be force ...

  2. IOS设计模式的六大设计原则之接口隔离原则(ISP,Interface Segregation Principle)

    定义 客户端不应该依赖它不需要的接口: 一个类对另一个类的依赖应该建立在最小的接口上. 定义解读 定义包含三层含义: 一个类对另一个类的依赖应该建立在最小的接口上: 一个接口代表一个角色,不应该将不同 ...

  3. 深入理解JavaScript系列(21):S.O.L.I.D五大原则之接口隔离原则ISP

    前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第4篇,接口隔离原则ISP(The Interface Segregation Principle). 英文原文:htt ...

  4. 设计模式 第一天 UML图,设计模式原则:开闭原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则,简单工厂模式

    1 课程大纲 2 UML的概述 总结: UML unified model language 统一建模语言 一共有十种图: 类图 用例图 时序图 * 对象图 包图 组件图 部署图 协作图 状态图 (最 ...

  5. 最简单直接地理解Java软件设计原则之接口隔离原则

    理论性知识 定义 接口隔离原则, Interface Segregation Principle,(ISP). 一个类对应一个类的依赖应该建立在最小的接口上: 建立单一接口,不要建立庞大臃肿的接口: ...

  6. 设计模式学习--面向对象的5条设计原则之接口隔离原则--ISP

    一.ISP简介(ISP--Interface Segregation Principle): 使用多个专门的接口比使用单一的总接口要好.一个类对另外一个类的依赖性应当是建立在最小的接口上的.一个接口代 ...

  7. C# 实例解释面向对象编程中的接口隔离原则

    在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...

  8. [设计模式]<<设计模式之禅>>关于接口隔离原则

    在讲接口隔离原则之前,先明确一下我们的主角——接口.接口分为两种: ● 实例接口(Object Interface),在Java中声明一个类,然后用new关键字产生一个实例,它是对一个类型的事物的描述 ...

  9. 设计模式之六大原则——接口隔离原则(ISP)

    设计模式之六大原则——接口隔离原则(ISP)  转载于:http://www.cnblogs.com/muzongyan/archive/2010/08/04/1792528.html 接口隔离原则 ...

随机推荐

  1. Android 蓝牙开发(1)

    普通蓝牙设备官方文档 Android 平台包含蓝牙网络堆栈支持,凭借此支持,设备能以无线方式与其他蓝牙设备交换数据.应用框架提供了通过 Android Bluetooth API 访问蓝牙功能的途径. ...

  2. 剑指offer 12:二进制中1的个数

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 解法一:设置标志为flag=1,逐个位移至不同位置,比较是否为1. C++实现 class Solution { publi ...

  3. rocksdb和leveldb的bloom filter比较

    memtable中的bloom filter rocksdb在memtable中添加了prefix bloom filter,就是对key取prefix,然后把这个prefix加入到bloom fil ...

  4. 前端基础之BOM和DOM操作

    目录 BOM和DOM定义 windows对象 windows的子对象 navigator对象 screen对象 history对象 location对象 弹出框 警告框 确认框 提示框 计时相关 se ...

  5. Day_05

    01.error接口的使用 package main import "fmt" import "errors" func main() { //var err1 ...

  6. fiddler---Fiddler性能测试

    从上几篇文章中我们了解到Fiddler可以帮助我们做接口测试,修改断点,抓包等应用,但是你可能想想不到,Fiddler也能做简单的性能测试 性能测试 性能测试是通过自动化的测试工具模拟多种正常.峰值以 ...

  7. 简单web服务工作流程梳理

       一.用户访问web基本流转过程梳理 二.web框架粗略概括

  8. char数据类型

    char数据类型就是为了中文 一个中文占两个字节正好char是占用两个字节 char a='国'’; char类型必须使用单引号属于字符类型 双引号的是字符串类型如果使用等号两边数据类型不一致就是 不 ...

  9. CSS自定义字体的实现,前端实现字体压缩

    CSS中使用自定义字体,首先需要下载你需要的字体ttf或者otf文件 这里推荐一个网站:http://www.zitixiazai.org/ /********css中********/ @font- ...

  10. web-综合题2

    地址 http://cms.nuptzj.cn/ 0x01  很有意思的一题综合题,确实包含的内容比较多 打开页面 把能打开的都打开,能看的都看一下 几个重点的信息 一段hash e045e454c1 ...