4.接口隔离原则(Interface Segregation Principle)
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)的更多相关文章
- 设计模式六大原则(四):接口隔离原则(Interface Segregation Principle)
接口隔离原则(ISP)定义: 客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 问题由来: 类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不 ...
- 接口隔离原则(Interface Segregation Principle, ISP)
使用多个专门的接口,而不使用单一的总接口 接口隔离有两种定义: Clients should not be forced to depend upon interfaces that they don ...
- 面象对象设计原则之四:接口隔离原则(The Interface Segregation Principle,ISP)
接口隔离原则定义如下: 接口隔离原则(Interface Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口. 根 ...
- 设计模式之六大原则——接口隔离原则(ISP)
设计模式之六大原则——接口隔离原则(ISP) 转载于:http://www.cnblogs.com/muzongyan/archive/2010/08/04/1792528.html 接口隔离原则 ...
- 设计模式值六大原则——接口隔离原则 (ISP)
接口隔离原则 Interface Segregation Principle 定义: 客户端不应该依赖它不需要的接口 类间的依赖关系应该建立在最小的接口上 我们可以把这两个定义概括为一句话:建立 ...
- 【面向对象设计原则】之接口隔离原则(ISP)
接口隔离原则(Interface Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口. 从接口隔离原则的定义可以看 ...
- Java设计原则—接口隔离原则(转)
接口隔离原则 Interface Segregation Principle 定义: 客户端不应该依赖它不需要的接口 类间的依赖关系应该建立在最小的接口上 我们可以把这两个定义概括为一句话:建立 ...
- 接口分离原则(Interface Segregation Principle)
接口分离原则(Interface Segregation Principle)用于处理胖接口(fat interface)所带来的问题.如果类的接口定义暴露了过多的行为,则说明这个类的接口定义内聚程度 ...
- ISP(Interface Segregation Principle),接口隔离原则
ISP(Interface Segregation Principle),接口隔离原则 它要求如下: ① 一个类对另一个类的依赖性要建立在最小接口上. ② 使用多个专门的接口比使用单一的总接口要好 ...
- 接口隔离原则(Interface Segregation Principle,ISP)
接口隔离原则: 1.使用多个专门的接口比使用单一的总接口要好. 2.一个类对另外一个类的依赖性应当是建立在最小的接口上的. 3.一个接口代表一个角色,不应当将不同的角色都交给一个接口.没有关系的接口合 ...
随机推荐
- 【转】使用Python的IDE:Eclipse+PyDev
原文网址:http://www.crifan.com/try_with_python_ide_eclipse_pydev/ 之前已经介绍过了一些基本知识: [整理][多图详解]如何在Windows下开 ...
- 【转】bzero, memset ,setmem 区别
原文网址:http://blog.csdn.net/agathe/article/details/6066157 bzero 原型: extern void bzero(void *s, int n ...
- 【转】为eclipse安装python、shell开发环境和SVN插件
原文网址:http://www.crazyant.net/1185.html eclipse是一个非常好用的IDE,通常来说我们都用eclipse来开发JAVA程序,为了让开发python.shell ...
- uglifyjs使用
1.安装Nodejs:去这里下载并安装. 2.打开cmd,运行npm,node应该会有输出东西 3.如果在window上运行Node.js的npm报Error: ENOENT, stat 'C:\Us ...
- php的header()大全
<?php /*** Function: PHP header() examples (PHP) ** Desc: Some examples on how to use the header( ...
- 被投资人“送”入看守所 z
http://news.cnblogs.com/n/506969/ 拜读了[[畅言]读<被投资人“送”入看守所>一文有感]一文有感,很想跟作者探讨几句.虽然他的看法很有理性,但站在一个刑案 ...
- 读取raw目录中的文件数据
try { InputStream is2 = getResources().openRawResource(R.raw.info); InputStreamReader isr2 = new Inp ...
- DuiLib消息处理剖析
本来想自己写写duilib的消息机制来帮助duilib的新手朋友,不过今天发现已经有人写过了,而且写得很不错,把duilib的主干消息机制都说明了,我就直接转载过来了,原地址:http://blog. ...
- leetcode:Integer to Roman(整数转化为罗马数字)
Question: Given an integer, convert it to a roman numeral. Input is guaranteed to be within the rang ...
- Chapter7:类
关于this指针 成员函数通过一个名为this的额外的隐式参数来访问调用它的对象.当我们调用一个成员函数时,用请求该函数的对象初始化this. total.isbn(); //等价于编译器重写为 Sa ...