1.定义

客户端不应该依赖它不需要的接口;

一个类对另一个类的依赖应该建立在最小的接口上。

2.定义解读

定义包含三层含义:

  • 一个类对另一个类的依赖应该建立在最小的接口上;
  • 一个接口代表一个角色,不应该将不同的角色都交给一个接口,因为这样可能会形成一个臃肿的大接口;
  • 不应该强迫客户依赖它们从来不用的方法。

接口隔离原则有点像单一职责原则,但是也有区别,在单一职责原则中,一个接口可能有多个方法,提供给多种不同的调用者所调用,但是它们始终完成同一种功能,因此它们符合单一职责原则,却不符合接口隔离原则,因为这个接口存在着多种角色,因此可以拆分成更多的子接口,以供不同的调用者所调用。比如说,项目中我们通常有一个Web服务管理的类,接口定义中,我们可能会将所有模块的数据调用方法都在接口中进行定义,因为它们都完成的是同一种功能:和服务器进行数据交互;但是对于具体的业务功能模块来说,其他模块的数据调用方法它们从来不会使用,因此不符合接口隔离原则。

3.优点

使用接口隔离原则,意在设计一个短而小的接口和类,符合我们常说的高内聚低耦合的设计思想,从而使得类具有很好的可读性、可扩展性和可维护性。

4.问题提出

类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类C来说不是最小接口,而类B和类D必须去实现它们不需要的方法。下面通过一个UML图来说明这种现象:

在这里,我们定义了一个动物活动的接口IAnimal,里面有4个方法:飞行fly、行走walk、吃eat和工作work,然后分别用人类People和鸟类Bird实现了这个接口。中国人类ChinesePeople和鹦鹉类Parrot通过接口IAnimal分别依赖类People和类Bird。很明显,对于ChinesePeople来说,fly方法是多余的,因为人不会飞;对于Parrot类来说,work方法是多余的,因为鹦鹉不需要工作。接口IAnimal对于类ChinesePeople和类Parrot来说不是最小接口。

5.解决方案

将臃肿的接口IAnimal拆分为独立的几个接口,类ChinesePeople和类Parrot分别与它们需要的接口建立依赖关系,也就是采用接口隔离原则。修改后的UML图如下所示:

6.示例

import Foundation

@objc protocol IAnimal
{
optional func walk();
func eat();
} protocol IPeople
{
func work();
} protocol IBird
{
func fly();
} class People: NSObject, IAnimal, IPeople
{
func walk()
{
print("People walk");
} func eat()
{
print("People eat");
} func work()
{
print("People work");
}
} class Bird: NSObject, IAnimal, IBird
{
func eat()
{
print("Bird eat");
} func fly()
{
print("Bird Fly");
}
} class ChinesePeople
{
var chinesePeople: protocol<IAnimal, IPeople>?; func peopleWalk()
{
chinesePeople?.walk!();
} func peopleEat()
{
chinesePeople?.eat();
} func peopleWork()
{
chinesePeople?.work();
}
} class Parrot
{
var parrot: protocol<IAnimal, IBird>?; func parrotEat()
{
parrot?.eat();
} func parrotFly()
{
parrot?.fly();
}
} let chinesePeople = ChinesePeople();
chinesePeople.chinesePeople = People();
chinesePeople.peopleEat(); //打印:People eat let parrot = Parrot();
parrot.parrot = Bird();
parrot.parrotEat(); //打印:Bird eat

说明:从UML图可以看到,遵守接口隔离原则,会使代码量增加不少,源码中也是这样;实际上,IOS在定义协议的时候,可以设置方法为可选实现(optional)和必须实现(默认值),我们可以设置work方法和fly方法为可选实现的方法,这样在类People和类Bird中,这两个方法可以根据需要来决定是否实现。采用这种方式,功能上实现是没有问题,对于简单的接口来说,也便于维护和管理。但是,当方法随着业务需求的增加而不断增加的话,如果我们不应用接口隔离原则,那么就可能形成一个庞大臃肿的接口,这样的接口的可维护性和重用性是很差的。因此,我们应该尽量细化接口,本篇将一个接口变更为3个专用的接口所采用的就是接口隔离原则。在项目开发中,依赖几个专用的接口要比依赖一个综合的接口更加灵活。通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

虽然接口隔离原则很有意义,但在实际项目中,应该注意度的把握,接口设计的过大或过小都不好,应该根据实际情况多思考再进行设计。

4.接口隔离原则(Interface Segregation Principle)的更多相关文章

  1. 设计模式六大原则(四):接口隔离原则(Interface Segregation Principle)

    接口隔离原则(ISP)定义: 客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 问题由来: 类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不 ...

  2. 接口隔离原则(Interface Segregation Principle, ISP)

    使用多个专门的接口,而不使用单一的总接口 接口隔离有两种定义: Clients should not be forced to depend upon interfaces that they don ...

  3. 面象对象设计原则之四:接口隔离原则(The Interface Segregation Principle,ISP)

    接口隔离原则定义如下: 接口隔离原则(Interface  Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口. 根 ...

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

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

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

    接口隔离原则 Interface Segregation Principle    定义: 客户端不应该依赖它不需要的接口 类间的依赖关系应该建立在最小的接口上 我们可以把这两个定义概括为一句话:建立 ...

  6. 【面向对象设计原则】之接口隔离原则(ISP)

    接口隔离原则(Interface  Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口. 从接口隔离原则的定义可以看 ...

  7. Java设计原则—接口隔离原则(转)

    接口隔离原则 Interface Segregation Principle    定义: 客户端不应该依赖它不需要的接口 类间的依赖关系应该建立在最小的接口上 我们可以把这两个定义概括为一句话:建立 ...

  8. 接口分离原则(Interface Segregation Principle)

    接口分离原则(Interface Segregation Principle)用于处理胖接口(fat interface)所带来的问题.如果类的接口定义暴露了过多的行为,则说明这个类的接口定义内聚程度 ...

  9. ISP(Interface Segregation Principle),接口隔离原则

    ISP(Interface Segregation Principle),接口隔离原则 它要求如下: ①  一个类对另一个类的依赖性要建立在最小接口上. ②  使用多个专门的接口比使用单一的总接口要好 ...

  10. 接口隔离原则(Interface Segregation Principle,ISP)

    接口隔离原则: 1.使用多个专门的接口比使用单一的总接口要好. 2.一个类对另外一个类的依赖性应当是建立在最小的接口上的. 3.一个接口代表一个角色,不应当将不同的角色都交给一个接口.没有关系的接口合 ...

随机推荐

  1. Filling a Path 模式

    Filling a Path When you fill the current path, Quartz acts as if each subpath contained in the path ...

  2. 如何使用java中的对象

    使用java中的对象,分2步: 1.创建一个对象: 2.使用对象的属性和方法. 见下面的示例代码: package com.imooc; //1.定义一个类 public class Telphone ...

  3. mysql中批量替换数据库中的内容的sql

    经过几次系统升级,遇到域名变了,文件存储目录变了,但之前被存到数据库里了,手动改太麻烦了,下面这个sql语句太给力了,屡试不爽. update table set body = replace(bod ...

  4. c# 读取IntPtr 中的数据 z

    c++的写法是这样的: LRESULT CPictureQueryDlg::OnQueryPicNty(WPARAM wp, LPARAM lp) { EnableWindow(TRUE); BYTE ...

  5. HDU5806 NanoApe Loves Sequence Ⅱ (BestCoder Round #86 C)二分

    分析:大于等于m的变成1,否则变成0,预处理前缀和,枚举起点,找到第一个点前缀和大于m即可 找第一个点可以二分可以尺取 #include <cstdio> #include <cst ...

  6. Linux常用文件管理命令

    Command Description cat filename 查看文件内容. cd dirname 改变所在目录. cp file1 file2 复制文件或目录. file filename 查看 ...

  7. AsyncTask简单获取网络图片的例子

    //首先呢,添加网络权限 android.permission.INTERNET //然后,布局View img=(Image)findViewById(R.id.imageView1); btn=( ...

  8. (转)android中利用 ViewPage 实现滑动屏

    最近实现了这样的一个效果:滑动界面出现拖拽效果,可翻动3屏,也可点击按钮翻动页面. 主要利用android.support.v4.view.ViewPager控件来实现. 第一个界面: 滑动屏幕: 换 ...

  9. QS之Intro

    公司里用Questa Sim做仿真,其实跟ModelSim差不多,总结常用的命令如下. 1 启动 vsim -gui 2 编译 -- VCOM vcom [-2008 | -2002 | -93 | ...

  10. 在Python中怎么表达True

    在Python中怎么表达True   为False的几种情况 0为False,其他所有数值皆为True 空串("")为False,其他所有字符串皆为True 空list([])为F ...