设计模式六大原则(4):接口隔离原则

2023-11-04

定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。

问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。

解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。

举例来说明接口隔离原则:

(图1 未遵循接口隔离原则的设计)

这个图的意思是:类A依赖接口I中的方法1、方法2、方法3,类B是对类A依赖的实现。类C依赖接口I中的方法1、方法4、方法5,类D是对类C依赖的实现。对于类B和类D来说,虽然他们都存在着用不到的方法(也就是图中红色字体标记的方法),但由于实现了接口I,所以也必须要实现这些用不到的方法。对类图不熟悉的可以参照程序代码来理解,代码如下:

interface I {
	public void method1();
	public void method2();
	public void method3();
	public void method4();
	public void method5();
}

class A{
	public void depend1(I i){
		i.method1();
	}
	public void depend2(I i){
		i.method2();
	}
	public void depend3(I i){
		i.method3();
	}
}

class B implements I{
	public void method1() {
		System.out.println("类B实现接口I的方法1");
	}
	public void method2() {
		System.out.println("类B实现接口I的方法2");
	}
	public void method3() {
		System.out.println("类B实现接口I的方法3");
	}
	//对于类B来说,method4和method5不是必需的,但是由于接口A中有这两个方法,
	//所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。
	public void method4() {}
	public void method5() {}
}

class C{
	public void depend1(I i){
		i.method1();
	}
	public void depend2(I i){
		i.method4();
	}
	public void depend3(I i){
		i.method5();
	}
}

class D implements I{
	public void method1() {
		System.out.println("类D实现接口I的方法1");
	}
	//对于类D来说,method2和method3不是必需的,但是由于接口A中有这两个方法,
	//所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。
	public void method2() {}
	public void method3() {}

	public void method4() {
		System.out.println("类D实现接口I的方法4");
	}
	public void method5() {
		System.out.println("类D实现接口I的方法5");
	}
}

public class Client{
	public static void main(String[] args){
		A a = new A();
		a.depend1(new B());
		a.depend2(new B());
		a.depend3(new B());
		
		C c = new C();
		c.depend1(new D());
		c.depend2(new D());
		c.depend3(new D());
	}
}

可以看到,如果接口过于臃肿,只要接口中出现的方法,不管对依赖于它的类有没有用处,实现类中都必须去实现这些方法,这显然不是好的设计。如果将这个设计修改为符合接口隔离原则,就必须对接口I进行拆分。在这里我们将原有的接口I拆分为三个接口,拆分后的设计如图2所示:


(图2 遵循接口隔离原则的设计)

照例贴出程序的代码,供不熟悉类图的朋友参考:

interface I1 {
	public void method1();
}

interface I2 {
	public void method2();
	public void method3();
}

interface I3 {
	public void method4();
	public void method5();
}

class A{
	public void depend1(I1 i){
		i.method1();
	}
	public void depend2(I2 i){
		i.method2();
	}
	public void depend3(I2 i){
		i.method3();
	}
}

class B implements I1, I2{
	public void method1() {
		System.out.println("类B实现接口I1的方法1");
	}
	public void method2() {
		System.out.println("类B实现接口I2的方法2");
	}
	public void method3() {
		System.out.println("类B实现接口I2的方法3");
	}
}

class C{
	public void depend1(I1 i){
		i.method1();
	}
	public void depend2(I3 i){
		i.method4();
	}
	public void depend3(I3 i){
		i.method5();
	}
}

class D implements I1, I3{
	public void method1() {
		System.out.println("类D实现接口I1的方法1");
	}
	public void method4() {
		System.out.println("类D实现接口I3的方法4");
	}
	public void method5() {
		System.out.println("类D实现接口I3的方法5");
	}
}

接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。本文例子中,将一个庞大的接口变更为3个专用的接口所采用的就是接口隔离原则。在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

说到这里,很多人会觉的接口隔离原则跟之前的单一职责原则很相似,其实不然。其一,单一职责原则原注重的是职责;而接口隔离原则注重对接口依赖的隔离。其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节;而接口隔离原则主要约束接口接口,主要针对抽象,针对程序整体框架的构建。

采用接口隔离原则对接口进行约束时,要注意以下几点:

  • 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
  • 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
  • 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。

运用接口隔离原则,一定要适度,接口设计的过大或过小都不好。设计接口的时候,只有多花些时间去思考和筹划,才能准确地实践这一原则。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式六大原则(4):接口隔离原则 的相关文章

  • Spring源码学习之BeanDefinition源码解析

    本文作者 磊叔 GLMapper本文链接 https juejin cn post 6844903553820000269 Bean的定义主要由BeanDefinition来描述的 作为Spring中用于包装Bean的数据结构 今天就来看看
  • Chain of Responsibility:责任链模式

    现有多个处理者 这些处理者可以处理不同的请求 这些处理者有等级关系 每个处理者都有更上级的处理者 对于最上级的处理者 可以没有上级 对于一个上级处理者 可以有多个下级处理者 客户端发出了一个请求 请求被传递给一个最下级处理者 而该处理者无法
  • 设计模式的 C++ 实现---原型模式

    前文回顾 单例模式 一 单例模式 二 观察者模式 简单工厂模式 工厂方法模式 一 工厂方法模式 二 抽象工厂模式 一 抽象工厂模式 二 前言 原型模式指直接用一个已经存在的对象来创建一个新的对象 然后对新对象进行稍微修改即可 类似复制的操作
  • 设计模式-单一职责原则介绍与理解

    描述 一个类应该专注于实现一个功能 好处 便于代码复用 举例 俄罗斯方块游戏 首先可以想到的是游戏逻辑与界面的分离 也就是说逻辑一个类 界面部分一个类 这样做的好处就是我们可以复用游戏逻辑的代码 例如我们用java写了一个基于PC端的俄罗斯
  • C++ 装饰器模式

    什么是装饰器模式 装饰器模式是一种结构型设计模式 实现了在不改变现有对象结构的的同时又拓展了新的功能 装饰器本质上是对现有对象的重新包装 同时装饰器又称为封装器 如何理解装饰器模式 以笔记本电脑为例 当我们购买了一台新笔记本电脑 但我们发现
  • 设计模式之享元模式

    一 背景 在面向对象程序设计过程中 有时会面临要创建大量相同或相似对象实例的问题 创建那么多的对象将会耗费很多的系统资源 它是系统性能提高的一个瓶颈 例如 围棋和五子棋中的黑白棋子 图像中的坐标点或颜色 局域网中的路由器 交换机和集线器 教
  • 设计模式--组合模式

    组合模式 又叫部分整体模式 属于结构型模式 基本原理 以树形的结构将相似的对象组合起来 主要流程 1 创建对象 2 在对象中设置用来存放下一级相似对象的数据结构 3 在对象中设置增删改查等功能 注意 这种模式和数据结构中的树形结构相似 in
  • 计算资源合并模式——云计算架构常用设计模式

    背景 云计算的解决方案中 最初设计可能有意遵循关注点分离的设计原则 把操作分解为独立的计算单元以便可以单独托管和部署 然而 虽然这种策略可以帮助简化解决方案的逻辑实现 但是在同一个应用程序中要部署大量的计算单元 这会增加运行时的托管成本 并
  • 简单工厂模式

    简单工厂模式 一 概念 从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫做静态工厂方法 StaticFactory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简
  • 设计模式——导论

    作为软件开发人员 我们在平时工作的过程中 往往需要编写很多的代码来实现我们的需求 很多的时候会造成代码臃肿和代码冗余的情况 这个时候我们需要引入一个理念 设计模式 设计模式存在的意义在于 1 使得我们的代码更加精炼 2 使我们代码的可读性更
  • 程杰“大话设计模式”中的设计原则

    单一职责原则 SRP 就一个类而言 应该仅有一个引起它变化的原因 如果一个类承担的职责过多 就等于把这些职责耦合在了一起 一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力 这种耦合会导致脆弱的设计 当发生变化时 设计会遭受到意想不到
  • 设计模式-建造者模式

    文章目录 建造者模式 创建复杂对象的优雅方式 什么是建造者模式 建造者模式的使用场景 优缺点 示例 使用建造者模式创建电脑对象 建造者模式 创建复杂对象的优雅方式 在软件开发中 有时候我们需要创建具有复杂结构和多个组件的对象 直接在客户端代
  • 第12课:生活中的构建模式——想要车还是庄园

    用程序来模拟生活 从剧情中思考构建模式 与工厂模式的区别 与组合模式的区别 构建模式的模型抽象 类图 基于升级版的实现 模型说明 应用场景 故事剧情 下周就要过年了 这是 Tony 工作后的第一个春节 还是在离家这么远的北京工作 所以肯定不
  • 设计模式学习笔记-工厂模式

    设计模式学习笔记 工厂模式 作用 实现了创建者和调用者的分离 详细分类 简单工厂模式 用来生产同一等级结构中的任意产品 对于增加新的产品 必须要扩展已有的代码 工厂方法模式 用来生产同一等级结构中的固定产品 支持增加任意产品 抽象工厂模式
  • 设计模式——State(状态)模式

    目录 前言 1 定义 2 适用性 3 结构 3 1 结构图 3 2 参与者 4 应用举例 4 1 State TcpState 4 2 Context TcpConnection 4 3 ConcreteState ListeningTcp
  • 哈工大2020软件构造Lab3实验报告

    本项目于4 21日实验课验收 更新完成 如果有所参考 请点点关注 点点赞GitHub Follow一下谢谢 2020春计算机学院 软件构造 课程Lab3实验报告 Software Construction 2020 Spring Lab 3
  • JavaScript设计模式-02-单例模式

    Javascript 设计模式 02 单例模式 简介 单例就是保证一个类只有一个实例 实现的方法一般是先判断实例是否存在 如果存在直接返回 如果不存在就创建了再返回 确保了一个类只有一个实例对象 在JavaScript里 单例作为一个命名空
  • 泛型与反射机制在JDBC和Servlet编程中的实践

    写在前面 泛型与反射是java中的两种强大机制 可以很好的提高代码的灵活性和复用性 本篇文章向大家展现在JDBC和Servlet编程场景下反射和泛型技术的实践 通过灵活使用这两种机制打造 高度可复用的JDBC和Servlet代码 1 JDB
  • Java设计模式:模板方法模式

    作者主页 欢迎来到我的技术博客 个人介绍 大家好 本人热衷于 Java后端开发 欢迎来交流学习哦 如果文章对您有帮助 记得 关注 点赞 收藏 评论 您的支持将是我创作的动力 让我们一起加油进步吧 文章目录 一 模板方法模式的定义 二 模板方
  • 自动化测试面试题(附答案)

    1 自动化代码中 用到了哪些设计模式 单例设计模式 工厂模式 PO设计模式 数据驱动模式 面向接口编程设计模式 2 什么是断言 Assert 断言Assert用于在代码中验证实际结果是不是符合预期结果 如果测试用例执行失败会抛出异常并提供断

随机推荐

  • 偏微分方程(Partial Differential Equation II)

    数学物理方法 正交曲面坐标系下的分离变量 球函数 勒让德方程的解 勒让德函数 连带勒让德函数 球谐函数 柱函数 贝塞尔方程的解 贝塞尔函数 球贝塞尔方程 偏微分方程 Partial Differential Equation I 偏微分方程
  • php网页如何适应手机端,PC网页的移动端适配兼容性应该如何实现自动适配

    概念 移动时代的今天 现如今随着智能手机的不断发展 移动端搜索的比例也在不断增加 而传统的PC站点在手机端的用户体验度很差 这容易导致大量用户的流失 所以做一个对应的手机站是非常有必要的前端代码的编写永远逃不过 兼容 二词 从前PC时代 因
  • 第四届“泰迪杯”数据分析技能赛通知

    各有关单位 为推广我国高校数据分析实践教学 培养学生数据分析的应用和创新能力 增加校企交流合作和信息共享 提升我国高校的教学质量和企业的竞争能力 由泰迪杯数据分析技能赛组织委员会主办 广东泰迪智能科技股份有限公司承办 广东省工业与应用数学学
  • cgminer 2.2.4 参数详解!

    日期 2012 02 13 分类 Cgminer 版权声明 转载时请以超链接形式标明文章原始出处和作者信息及本声明 http bitcoin blogbus com logs 192244223 html cgminer2 2 4已经发布
  • 用Cookie添加登录界面的记住密码功能

    在网上看到很多关于cookie记录登录密码的功能 但是大部分都是jsp界面 最近刚好有个项目用到了cookie功能 所以编写了这个介绍 补全一下 1 第一步 首先需要在登录界面中写一个form表单 这个不用多说
  • kubernetes理论概念详情(K8S)

    1 优势 2 四组基本概念 3 核心组件 4 其他概念 5 基本命令
  • frp安全内网穿透,安全远程windows,暴露服务

    目录 概述 公网服务器端 内网Windows客户端 外网Windows客户端 附加 暴露多台内网Windows客户端 附加 暴露服务 总结 概述 frp 是一个专注于内网穿透的高性能的反向代理应用 支持 TCP UDP HTTP HTTPS
  • pip在线安装selenium

    最近发布了selenium3 0 但是会有很多莫名其妙的报错 原来可执行的代码也报错了 所以要重新安装回2 0 一 2 7 10之后的python安装包自带了Pip和setuptools 如果你没有安装可以去官网单独下载然后安装 a 下载地
  • js取值方式

    1 根据class id 取 input 标签的value 值 jQuery className val idName val javaScript document getElementById idName value 2 根据clas
  • GPRS本质论

    GPRS DTU最基本的用法是 在DTU中放入一张开通GPRS功能的SIM卡 DTU上电后先注册到GPRS网络 然后通过GPRS网络和数据处理中心建立连接 这条连接涉及了无线网络运营商 因特网宽 带供应商 用户公司的网络情况 以及用户的电脑
  • 使用ELK收集网络设备日志的案例

    简介 随着机房内的服务器和网络设备增加 日志管理和查询就成了让系统管理员头疼的事 系统管理员遇到的常见问题如下 1 日常维护过程中不可能登录到每一台服务器和设备上去查看日志 2 网络设备上的存储空间有限 不可能存储日期太长的日志 而系统出现
  • 解决github下载慢的问题可以提速【1M/s】

    1 问题描述 在github上下载项目时 下载速度经常都是20k s的速度下载 项目过大时还经常会显示网络出错导致下载失败 2 原因 我想对于经常使用git的人来讲 很可能已经知道了 对于新手刚接触git的人来讲 可能你只知道github
  • 分享!一文简析RASP技术

    众所周知 log4j 2 x安全事件引起了轩然大波 对于信息安全从业者来讲可以称之为 家喻户晓 与之同时引起大家关注的是RASP Runtime application self protection 技术 该技术在2014年Gartner
  • 强化学习奖励函数的归一化

    将每个奖励分量进行归一化 然后再分配权重
  • 9月17日服务器维护,2020年09月17日维护公告

    亲爱的玩家 为了保证服务器的稳定和服务质量 大话西游2免费版 将于2020年09月17日早上8 00停机 进行每周例行的维护工作 维护时间为早上08 00至09 30 同时 本次停机还将发布最新的客户端补丁 patch2 0 824 如果在
  • 从零开始学习JavaScript:轻松掌握编程语言的核心技能③

    从零开始学习JavaScript 轻松掌握编程语言的核心技能 一 JavaScript条件语句 1 1 if Else 语句 1 2 if else if else 语句 1 3 switch 语句 1 4 for 循环 1 5 while
  • 线性插值_c语言实现

    这是个很简单的数学工具 有的问题可能就只需要简单的数学工具就能解决 线性插值 线性插值法 是指使用连接两个已知量的直线来确定在这两个已知量之间的一个未知量的值的方法 线性插值相比其他插值方式 如抛物线插值 具有简单 方便的特点 线性插值可以
  • 基于Zxing的二维码生成和二维码扫描

    最近又在倒腾二维码 发现网上的教程都不够用 所以把之前整合的二维码Demo有拿出来重新添加些功能 这里也算是重新学习吧 当然对于二维码 相信大家都很熟悉了 这里就不多说 本项目是基于Zxing的开源项目开发的 这里用的Demo是之前网上搜的
  • 【计算机组成原理】(四)原码补码的加减乘除

    各种码的作用 模运算的性质 3 1 12 9 9 0 12 9 21 1 12 9 33 2 12 9 15 2 12 9 我们发现等号右边都是 9 相当于等号的左边的数除去12的余数都是9 那我们就说这几个等好左边的数 在mod12的情况
  • 设计模式六大原则(4):接口隔离原则

    定义 客户端不应该依赖它不需要的接口 一个类对另一个类的依赖应该建立在最小的接口上 问题由来 类A通过接口I依赖类B 类C通过接口I依赖类D 如果接口I对于类A和类B来说不是最小接口 则类B和类D必须去实现他们不需要的方法 解决方案 将臃肿