-
2022-03-17 21:03:09
一、接口隔离原则定义
接口隔离原则定义如下:
接口隔离原则(Interface Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
二、接口隔离原则描述
根绝接口隔离原则,当一个接口太大时,我们需要将它分割成一些细小的接口,使用该接口的客户端只需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事情,干该干的事请。这里的"接口"往往有两种不同的定义:一种是指一个类型所具有的方法特征的集合,仅仅是一种逻辑上的抽象;另外一种是某种语言上具体的"接口"定义,比如Java语言的
interface
。对于这两种不同的含义,接口隔离原则表达以及含义所以不同:- 当把”接口“理解成一个类型所具有的方法特性的集合时,就是一种逻辑上的概念,接口的划分将直接带来类的划分。可以把接口理解成角色,一个接口只能代表一个角色,每个角色都有它特定一个接口,此时这个原则可以叫做角色隔离原则。
- 如果把"接口"理解成狭义的特定语言接口,那么接口隔离原则表达的意思就是接口仅仅提供客户端需要的行为,客户端不需要的行为则隐藏起来,应当为客户端提供尽可能小的接口,而不要提供大的总接口。在面向对象编程语言中,实现一个接口类就要实现该接口定义的所有方法,因此大的总接口使用起来不一定很方便,为了使接口的职责单一,需要把大接口中的方法根据其职责不同放到不同的小接口中,确保每个接口使用起来都很方便,并都承担某一单一角色。接口应该尽量细化,同时接口中的方法应该尽量少,每个接口中只包含一个客户端(如子模块或者业务逻辑类)所需的方法即可,这种机制也称为“定制服务”,即为不同的客户端提供宽窄不同的接口。
三、接口隔离原则栗子
不满足接口隔离原则
现有一个接口
CustomerDataDisplay
,包含了dataRead()
、transformToXml()
、createChart()
、displayChart()
、createReport()
、displayReport()
方法,方法说明如下:dataRead()
:数据读取。transformToXml()
:数据转成xml格式。createChart()
:创建图表。displayChart()
:显示图表。createReport()
:创建报表。displayReport()
:显示报表。
代码如下:
public interface CustomerDataDisplay { List<CustomerData> dataRead(); void transformToXml(); void createChart(); void displayChart(); void createReport(); void displayReport(); }
先有一个图表类
ChartClass
实现了CustomerDataDisplay
接口,该类就要实现接口的全部方法,正常来说ChartClass
只需要createChart()
、displayChart()
方法即可,因为CustomerDataDisplay
接口方法太多了,承担了太多职责,颗粒度太大了ChartClass
类不得不空实现其他方法,违背了接口隔离原则。代码如下:public class ChartClass implements CustomerDataDisplay { public List<CustomerData> dataRead(){ // 空实现 } public void transformToXml(){ // 空实现 } public void createChart(){ // 创建图表 } public void displayChart(){ // 显示图表 } public void createReport(){ // 空实现 } publicvoid displayReport(){ // 空实现 } }
重构满足接口隔离原则
我们可以根据业务职业将
CustomerDataDisplay
接口分为DataHandler
、XMLTransformer
、ChartHandler
、ReportHandler
四个接口,这四个接口职责分别是:DataHandler
:数据业务处理接口。XMLTransformer
:XML转换接口。ChartHandler
:图表业务处理接口。ReportHandler
:报表业务处理接口。
代码如下:
public interface DataHandler { List<CustomerData> dataRead(); }
public interface XMLTransformer { void transformToXml(); }
public interface ChartHandler { void createChart(); void displayChart(); }
public interface ReportHandler { void createReport(); void displayReport(); }
重构之后每个接口都承担自己的职责,灵活性很高,使用起来很方便,每个接口中都只包含和自己业务相关的方法,不会存在和自己无关的方法,达到了高内聚、松耦合的效果。
在使用接口隔离原则时我们要控制接口的颗粒度,颗粒度不能太大,也不能太小。如果太小就会造成接口泛滥,不利于维护;接口入如果太大就会违背接口隔离原则,灵活性较差,使用起来不方便。一般来说接口中仅包含某业务模块的方法即可,不应该有其他业务模块的方法。
更多相关内容 -
PHP面向对象五大原则之接口隔离原则(ISP)详解
2020-12-20 07:38:21本文实例讲述了PHP面向对象五大原则之接口隔离原则(ISP)。分享给大家供大家参考,具体如下: 设计应用程序的时候,如果一个模块包含多个子模块,那么我们应该小心对模块...接口隔离原则(Interface Segregation Prin -
接口隔离原则ISP.zip
2021-01-10 19:59:20接口隔离原则ISP.zip -
简单理解遵循接口隔离原则的Java设计模式编程
2020-09-02 20:07:34主要介绍了遵循接口隔离原则的Java设计模式编程,针对Java编程中interface接口方面的编写进行约束,需要的朋友可以参考下 -
接口隔离原则_动力节点Java学院整理
2020-08-29 18:18:57主要介绍了接口隔离原则,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
接口隔离原则
2021-01-17 00:32:23目录一、什么是接口隔离原则(Interface Segregation Principle)二、不符合示例1. UML图2.代码3.分析三、改进1. UML图2. 代码3. 分析 一、什么是接口隔离原则(Interface Segregation Principle) 定义: 客户端不...一、什么是接口隔离原则(Interface Segregation Principle)
定义:
- 客户端不应该依赖它不需要的接口;
- 一个类对另一个类的依赖应该建立在最小的接口上。
概括的说就是:建立单一接口,不要建立臃肿庞大的接口。(接口尽量细化,同时接口中的方法尽量少。)
提供给每个模块的都应该是单一接口,提供给几个模块就应该有几个接口,而不是建立一个庞大的臃肿的接口,容纳所有的客户端访问。接口是我们设计时对外提供的契约,通过分散定义多个接口,可以预防未来变更的扩散,提高系统的灵活性和可维护性。
可以简要解释为以下四点:
- 接口要尽量小
这是接口隔离原则的核心定义,不出现臃肿的接口(Fat Interface),但是“小”是有限度的,首先就是不能违反单一职责原则。
根据接口隔离原则拆分接口时,首先必须满足单一职责原则。 - 接口要高内聚
高内聚就是要提高接口、类、模块的处理能力,减少对外的交互。
具体到接口隔离原则就是,要求在接口中尽量少公布public方法,接口是对外的承诺,承诺地越少对系统开发越有利,变更的风险也就越少,同时也有利于降低成本。 - 定制服务
定制服务就是单独为一个个体提供优良的服务。 - 接口设计是有限度的
接口的设计粒度越小,系统越灵活,这是不争的事实。但是,灵活的同时也带来了结构的复杂化,开发难度增加,可维护性降低,这不是一个项目或产品所期望看到的,所以接口设计一定要注意适度,这个度只能根据经验和常识判断,没有一个固化或可测量的标准。
二、不符合示例
1. UML图
2.代码
//接口 interface Interface1 { void operation1(); void operation2(); void operation3(); void operation4(); void operation5(); }
class B implements Interface1 { public void operation1() { System.out.println("B 实现了 operation1"); } public void operation2() { System.out.println("B 实现了 operation2"); } public void operation3() { System.out.println("B 实现了 operation3"); } public void operation4() { System.out.println("B 实现了 operation4"); } public void operation5() { System.out.println("B 实现了 operation5"); } }
class D implements Interface1 { public void operation1() { System.out.println("D 实现了 operation1"); } public void operation2() { System.out.println("D 实现了 operation2"); } public void operation3() { System.out.println("D 实现了 operation3"); } public void operation4() { System.out.println("D 实现了 operation4"); } public void operation5() { System.out.println("D 实现了 operation5"); } }
class A { //A 类通过接口Interface1 依赖(使用) B类,但是只会用到1,2,3方法 public void depend1(Interface1 i) { i.operation1(); } public void depend2(Interface1 i) { i.operation2(); } public void depend3(Interface1 i) { i.operation3(); } }
class C { //C 类通过接口Interface1 依赖(使用) D类,但是只会用到1,4,5方法 public void depend1(Interface1 i) { i.operation1(); } public void depend4(Interface1 i) { i.operation4(); } public void depend5(Interface1 i) { i.operation5(); } }
3.分析
- 类 A 通过接口 Interface1 依赖类 B,类 C 通过接口 Interface1 依赖类 D,如果接口 Interface1 对于类 A 和类 C来说不是最小接口,那么类 B 和类 D 必须去实现他们不需要的方法。
- 按隔离原则应当这样处理:将接口 Interface1 拆分为独立的几个接口(这里我们拆分成 3 个接口),类 A 和类 C 分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
三、改进
1. UML图
2. 代码
public class Segregation1 { public static void main(String[] args) { // TODO Auto-generated method stub // 使用一把 A a = new A(); a.depend1(new B()); // A类通过接口去依赖B类 a.depend2(new B()); a.depend3(new B()); C c = new C(); c.depend1(new D()); // C类通过接口去依赖(使用)D类 c.depend4(new D()); c.depend5(new D()); } }
// 接口1 interface Interface1 { void operation1(); }
// 接口2 interface Interface2 { void operation2(); void operation3(); }
// 接口3 interface Interface3 { void operation4(); void operation5(); }
class B implements Interface1, Interface2 { public void operation1() { System.out.println("B 实现了 operation1"); } public void operation2() { System.out.println("B 实现了 operation2"); } public void operation3() { System.out.println("B 实现了 operation3"); } }
class D implements Interface1, Interface3 { public void operation1() { System.out.println("D 实现了 operation1"); } public void operation4() { System.out.println("D 实现了 operation4"); } public void operation5() { System.out.println("D 实现了 operation5"); } }
class A { // A 类通过接口Interface1,Interface2 依赖(使用) B类,但是只会用到1,2,3方法 public void depend1(Interface1 i) { i.operation1(); } public void depend2(Interface2 i) { i.operation2(); } public void depend3(Interface2 i) { i.operation3(); } }
class C { // C 类通过接口Interface1,Interface3 依赖(使用) D类,但是只会用到1,4,5方法 public void depend1(Interface1 i) { i.operation1(); } public void depend4(Interface3 i) { i.operation4(); } public void depend5(Interface3 i) { i.operation5(); } }
3. 分析
- 类 A 通过接口 Interface1 依赖类 B,类 C 通过接口 Interface1 依赖类 D,如果接口 Interface1 对于类 A 和类 C来说不是最小接口,那么类 B 和类 D 必须去实现他们不需要的方法
- 将接口 Interface1 拆分为独立的几个接口,类 A 和类 C 分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
- 接口 Interface1 中出现的方法,根据实际情况拆分为三个接口
-
深入理解JavaScript系列(21):S.O.L.I.D五大原则之接口隔离原则ISP详解
2021-01-19 18:55:46本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第4篇,接口隔离原则ISP(The Interface Segregation Principle)。 英文原文:... -
【软件架构设计原则】单一职责原则和接口隔离原则
2022-04-01 08:39:24文章目录 软件架构设计原则 单一职责原则 接口隔离原则 其他设计原则 软件架构设计原则 本文通过实例来讲解 单一职责原则 接口隔离原则 单一职责原则 单一职责(Simple Responsibility Pinciple, SRP) 是指不要存在...软件架构设计原则
本文通过实例来讲解
- 单一职责原则
- 接口隔离原则
单一职责原则
单一职责(Simple Responsibility Pinciple, SRP) 是指不要存在多于一个倒置类变更的原因。假设我们只有一个类负责两个职责,一旦发生需求变更,修改其中一个职责的逻辑代码,有可能导致另一个职责的功能发生故障。这样一来,这个类就存在两个导致类变更的原因。如何解决这个问题呢?
将两个职责用两个类来实现,进行解耦。后期需求变更维护互不影响。这样的设计,可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更引起的风险。总体来说就是一个类,接口或者方法只负责一项职责。代码实例,假设我们的课程有直播课和录播课。直播课不能快进和快退,录播课可以反复观看,功能职责不一样,先创建一个Course类
public class Course { public void study(String CourseName){ if ("直播课".equals(CourseName)){ System.out.println(CourseName+"直播课不能快进"); }else { System.out.println(CourseName+"可以反复观看"); } } }
调用代码:
public class Test { public static void main(String[] args) { Course course = new Course(); course.study("直播课"); course.study("录播课"); } }
从上面代码来看,Course类承担了两种处理逻辑。假如现在要对课程进行加密,直播课程和录播课程的加密逻辑不一样,必须修改代码。而修改代码的逻辑势必会相互影响,容易带来不可控的风险,我们对职责进行解耦,来看代码,分别创建两个类LiveCourse和ReplayCourse
LiveCourse类的代码:
public class LiveCourse { public void study(String courseName){ System.out.println(courseName+"直播课不能快进"); } }
ReplayCourse类代码:
public class ReplayCourse { public void study(String courseName){ System.out.println(courseName+"可以反复观看"); } }
调用代码如下:
public static void main(String[] args) { LiveCourse liveCourse = new LiveCourse(); liveCourse.study("直播课"); ReplayCourse replayCourse = new ReplayCourse(); replayCourse.study("录播课"); }
业务继续发展,课程需要做权限一条。没有付费的学员可以获取课程基本信息,已经付费的学员可以获取视频,即学习权限。那么在控制课程层面上至少有两个职责。我们可以把展示职责和管理职责分离开来,都实现同一个抽象依赖。设计一个顶层接口,创建ICourse接口:
public interface ICourse { //获取基本信息 String getCourseName(); //获取视频流 byte[] getCourseVideo(); //学习课程 void studyCourse(); //退款 void refundCourse(); }
我们可以把这个接口拆分成两个接口:ICourseInfo和ICourseManager。
ICourseInfo接口:
public interface ICourseInfo { //获取基本信息 String getCourseName(); //获取视频流 byte[] getCourseVideo(); }
ICourseManager
public interface ICourseManager { //学习课程 void studyCourse(); //退款 void refundCourse(); }
类图:
下面我们来看一下方法层面的单一职责设计。有时候我们会偷懒,把一个方法写成下面这样:private void modifyUserInfo(String username,String address){ username = "tom"; address = "xian" }
显然上面的方法承担了多个职责,既可以修改userName,也可以修改address,甚至更多,明显不符合单一职责。我们做如下修改,把这个方法拆成两个方法
private void modifyUserName(String username){ username = "tom"; } private void modifyAddress(String address){ address = "xian"; }
修改之后,开发起来简单,维护起来也变的简单,我们在实际开发中会有项目依赖、组合、聚合、这些关系,还有项目的规模、周期、技术人员的水平、对进度的把控、很多类都不符合单一职责,但是我们在编写代码的过程,尽可能地让接口和方法保持单一职责,对项目后期的维护是有很大的帮助的。
接口隔离原则
接口隔离原则(Interface Segregation Principle,ISP)是指多个专门的接口,而不是用第一总接口,客户端不应该依赖它不需要的接口。这个原则知道我们在设计接口时应当注意以下几点:
- 一个类对另一个类的依赖应该建立在最小接口之上。
- 建立单一接口,不要建立庞大臃肿的接口。
- 尽量细化接口,接口中的方法尽量少(适度)。
接口隔离原则符合我i们常说的高内聚、低耦合的设计思想,可以使类具有很好的可读性、可扩展性和可维护性。我们在设计接口的时候,要多花时间去思考,要考虑业务模型,包括对以后有可能发生变更的地方还要做一些预判。所以,对于抽象、对于业务模型的理解使非常重要的。
下面的代码是对一个动物行为进行抽象描述
IAnimal接口的代码如下:
public interface IAnimal { void eat(); void fly(); void swim(); }
Bird类:
public class Bird implements IAnimal { @Override public void eat() { } @Override public void fly() { } @Override public void swim() { } }
Dog类:
public class Dog implements IAnimal { @Override public void eat() { } @Override public void fly() { } @Override public void swim() { } }
可以看出,Bird的swim方法可能空着,Dog的fly()方法显然不可能实现。这时候我么就需要针对不同的动物行为来设计不同的接口,分别涉及IEatAnimal、IFlyAnimal和ISwimAnimal接口,代码:
IEatAnimal 接口:
public interface IEatAnimal { void eat(); }
IFlyAnimal接口
public interface IFlyAnimal { void fly(); }
ISwimAnimal接口:
public interface ISwimAnimal { void swim(); }
Dog只是先IEatAnimal 接口和ISwimAnimal 接口:
public class DogImpl implements ISwimAnimal,IEatAnimal { @Override public void swim() { } @Override public void eat() { } }
通过类图对比:
其他设计原则
后序还有:
- 迪米特原理
- 里氏替换原理
- 合成复用原理
-
c++接口隔离原则1
2022-08-08 17:44:55c++接口隔离原则1 -
【设计模式】软件设计七大原则 ( 接口隔离原则 | 代码示例 )
2021-08-24 10:54:09一、接口隔离原则简介、 二、接口隔离原则代码示例 ( 反面示例 )、 1、接口定义 ( 接口臃肿 )、 2、实现类 1、 3、实现类 2、 三、接口隔离原则代码示例 ( 推荐用法 )、 1、接口 1、 2、接口 2、 3、接口 3、 4、...文章目录
一、接口隔离原则简介
接口隔离原则 : 用 多个 专门的 接口 , 不使用 单一 的总接口 , 客户端 不应该依赖 它 不需要的 接口 ;
一个类 对 另一个类 的依赖 , 应该建立在 最小接口 上 ; 如果 有一个 大接口 , 里面有 很多方法 , 如果使用一个类 实现该接口 , 所有的类都要实现 ;
建立 功能 单一接口 , 不要建立 庞大 臃肿 的接口 ;
尽量细化接口 , 接口中的方法尽量少 ;
接口设计适度原则 : 接口隔离原则 中 最重要的就是 注意 适度原则 , 一定要适度 ;
接口设计的 过大 , 过小 , 都不合适 ; 设计接口时 , 多花时间去思考策划 ;
接口方法 尽量少 , 但要有限度 , 对接口进行细化 , 肯定能 提高系统设计的灵活性 , 但是如果 接口设计的过小 , 方法过少 , 则会 造成接口数量过多 , 提高整个程序设计的复杂性 ;
接口隔离原则 优点 : 符合 高内聚 , 低耦合 的 设计思想 , 使得类具有很好的 可读性 , 可扩展性 , 可维护性 ;
-
降低耦合 : 平时设计接口时 , 只暴露客户端需要的方法 , 客户端不需要的方法 , 直接隐藏起来 ; 只有专注的为一个模块提供定制服务 , 才能 建立最小的依赖关系 , 这样就降低了耦合程度 ;
-
提高内聚 : 减少对外交互 , 使用接口中最少的方法 , 完成最多的事情 ;
实际开发中 , 实践接口隔离原则时 , 也要根据业务场景 , 业务模型 , 以及以后有可能会发生变更的地方 , 对于这些做一些预判 , 抽象出业务模型很重要 ;
二、接口隔离原则代码示例 ( 反面示例 )
1、接口定义 ( 接口臃肿 )
package interfacesegregation; /** * 动物行为接口 * 该接口中声明的方法过多 , 方法分属于不同的类型 * 该接口可以进一步细化 */ public interface IAnimationAction { void eat(); void fly(); void walk(); void swim(); }
2、实现类 1
package interfacesegregation; /** * 定义 Dog 类 , 实现 IAnimationAction 接口 * 需要实现该接口下的所有方法 * 很明显狗不能飞 , fly 方法只能空着 , 没有实际意义 */ public class Dog implements IAnimationAction { @Override public void eat() { } @Override public void fly() { } @Override public void walk() { } @Override public void swim() { } }
3、实现类 2
package interfacesegregation; /** * 定义 Bird 类 , 实现 IAnimationAction 接口 * 需要实现该接口下的所有方法 * 很明显鸟不能游泳 , swim 方法只能空着 , 没有实际意义 */ public class Bird implements IAnimationAction { @Override public void eat() { } @Override public void fly() { } @Override public void walk() { } @Override public void swim() { } }
三、接口隔离原则代码示例 ( 推荐用法 )
1、接口 1
package interfacesegregation; public interface IEatAnimalAction { void eat(); }
2、接口 2
package interfacesegregation; public interface IFlyAnimalAction { void fly(); }
3、接口 3
package interfacesegregation; public interface ISwimAnimalAction { void swim(); }
4、接口 4
package interfacesegregation; public interface IWalkAnimalAction { void walk(); }
5、实现类
package interfacesegregation; /** * 狗可以 吃 / 走路 / 游泳 * 这里直接继承 3 个对应的接口 * 并实现接口中的方法 * * 细粒度接口可以组装 , 粗粒度接口无法拆分 */ public class Dog implements IEatAnimalAction, IWalkAnimalAction, ISwimAnimalAction { @Override public void eat() { } @Override public void swim() { } @Override public void walk() { } }
-
-
php接口隔离原则实例分析
2020-10-16 00:21:30主要介绍了php接口隔离原则,结合实例形式分析了PHP接口隔离原则的相关原理、使用方法及操作注意事项,需要的朋友可以参考下 -
单一职责原则和接口隔离原则区别的理解
2021-12-10 22:04:58网上对于两者的区别众说纷纭,总是一套理论下来跟没有说一样,下面说说自己的理解: 单一职责原则: 是将某一职责的方法全放在一个...设计模式六大原则(4):接口隔离原则_三级小野怪的专栏-CSDN博客_接口隔离原则定. -
接口隔离原则和单一职责原则区别
2021-04-04 01:47:11接口隔离原则和单一职责原则区别 单一职责原则是备受争议的原则,根据不同的业务逻辑,它会将系统功能模块划分成不同种类,产生多样的接口,同时每个接口尽量只包含一个功能(方法)。 而产生争议的原因就是这个业务... -
五、设计模式——接口隔离原则
2020-08-18 15:16:24客户端不应该被迫依赖于它不使用的方法(接口根据模块/业务拆分) -
Java设计模式-接口隔离原则
2019-03-11 08:40:15接口隔离原则 【Interface Segregation Principle】 定义1:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上(Clients should not be forced to depend upon interfaces that ... -
C# 之 接口隔离原则讲解
2020-07-26 20:47:08接口隔离原则的解释如下: 客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。 下面我将举出两个例子来讲解这个原则特性是怎么样的 . . . 1)第一个例子是一个女人在街上开着小汽车,... -
设计模式六大原则之接口隔离原则、迪米特法则详解
2020-11-18 15:26:24设计模式之六大原则之——接口隔离原则详解 1、接口隔离原则(Interface Segregation Principle,ISP) 概念 在将接口隔离原则之前,首先要明确“接口”的概念,接口分为两种: 实力接口 在Java中通过new关键子... -
接口隔离原则 接口隔离原则
2009-11-27 14:13:30接口隔离原则接口隔离原则接口隔离原则接口隔离原则 -
以C/C++语法浅谈六大设计原则(四)——接口隔离原则(Interface Segregation Principle)
2019-01-15 15:39:51一.前言 问题由来:有一接口类IBase,类A通过接口IBase依赖类B,类C通过接口IBase依赖类D,如果接口IBase对于类A和类B来说不是最小接口(除了自己所需要的方法外还存在...也就是采用接口隔离原则(Interface Segreg... -
设计模式六大原则(五)接口隔离原则
2019-01-07 17:02:25设计模式六大原则 定义:简称ISP。客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在...先看不使用接口隔离原则,代码会什么样: public class MadeFood { interface MadeFoodInter{ void mad... -
举例说明Java设计模式编程中ISP接口隔离原则的使用
2020-09-02 20:09:05主要介绍了Java设计模式编程中ISP接口隔离原则的使用,接口隔离原则主张一个类对另外一个类的依赖性应当是建立在最小的接口上,需要的朋友可以参考下