接口隔离原则,到底什么需要隔离?

接口隔离原则(Interface Segregation Principle, ISP)是SOLID五大设计原则之一,其核心思想是:客户端不应该被迫依赖于它不使用的方法;接口应当尽量小而专一,避免创建“胖”接口(即一个接口中定义了太多的方法)。

通过应用接口隔离原则,可以使系统更加灵活,维护性更高,并且减少类之间的耦合。

需要隔离的内容

  1. 方法:一个接口中不应包含过多的方法,特别是那些客户端不需要使用的方法。
  2. 实现:不同的接口实现应该针对特定的客户端需求,而不是一个通用的实现服务于所有客户端。
  3. 变化:接口的变化应该只影响到依赖于该接口的部分客户端,而不是所有客户端。

Java示例

假设我们设计一个系统,系统中有打印机(Printer)和复印机(Copier),同时也有一种设备是多功能一体机(MultiFunctionPrinter),即可以打印,也可以复印。

违反接口隔离原则的设计

// 胖接口
public interface Machine {
    void print();
    void copy();
}

public class Printer implements Machine {
    @Override
    public void print() {
        // 实现打印
        System.out.println("Printing document.");
    }

    @Override
    public void copy() {
        // 打印机不具备复印功能,但由于实现了Machine接口,这里必须提供空实现或抛出异常
        throw new UnsupportedOperationException("Copy not supported.");
    }
}

public class Copier implements Machine {
    @Override
    public void print() {
        // 复印机不具备打印功能,这里必须提供空实现或抛出异常
        throw new UnsupportedOperationException("Print not supported.");
    }

    @Override
    public void copy() {
        // 实现复印
        System.out.println("Copying document.");
    }
}

public class MultiFunctionPrinter implements Machine {
    @Override
    public void print() {
        System.out.println("Printing document.");
    }

    @Override
    public void copy() {
        System.out.println("Copying document.");
    }
}

在上面的设计中,PrinterCopier类被迫实现了它们不需要的方法,这违反了接口隔离原则。

符合接口隔离原则的设计

// 将接口拆分为更小的、专一的接口
public interface PrinterInterface {
    void print();
}

public interface CopierInterface {
    void copy();
}

// 单独实现打印功能的类
public class Printer implements PrinterInterface {
    @Override
    public void print() {
        System.out.println("Printing document.");
    }
}

// 单独实现复印功能的类
public class Copier implements CopierInterface {
    @Override
    public void copy() {
        System.out.println("Copying document.");
    }
}

// 实现多功能一体机,同时实现两个接口
public class MultiFunctionPrinter implements PrinterInterface, CopierInterface {
    @Override
    public void print() {
        System.out.println("Printing document.");
    }

    @Override
    public void copy() {
        System.out.println("Copying document.");
    }
}

在符合接口隔离原则的设计中,我们将Machine接口拆分为PrinterInterfaceCopierInterface,这样每个类只需关心它需要实现的功能。Printer类只实现打印接口,Copier类只实现复印接口,而MultiFunctionPrinter类则实现两个接口,从而提供了打印和复印功能。

好处

  1. 高内聚低耦合:每个接口都只负责一项职责,类之间的依赖关系更加明确。
  2. 灵活性增强:可以更容易地添加新功能或修改现有功能,而不会影响其他不相关的功能。
  3. 可维护性提高:当一个接口发生变化时,只需修改依赖于该接口的类,而不会影响其他类。

通过应用接口隔离原则,我们可以设计出更加清晰、灵活和可维护的系统。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/948364.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2街景两两对比程序,Trueskill计算评分代码,训练模型,预测街景

目录 0、Emeditor软件1、place pluse 2.0数据集2、街景主观感知两两对比程序3、Trueskill结果4、训练模型Resnet,Efficient,VIT等对比选择。5、模型预测6、其他数据处理/程序/指导!!!优势:全网最全最细&am…

【React+TypeScript+DeepSeek】穿越时空对话机

引言 在这个数字化的时代,历史学习常常给人一种距离感。教科书中的历史人物似乎永远停留在文字里,我们无法真正理解他们的思想和智慧。如何让这些伟大的历史人物"活"起来?如何让历史学习变得生动有趣?带着这些思考&…

Golang学习历程【第五篇 复合数据类型:数组切片】

Golang学习历程【第五篇 复合数据类型:数组&切片】 1. 数组(Array)1.1 数组的定义1.2 初始化数组1.3 数据的循环遍历1.4 多维数组 2. 切片(Slice)2.1 切片声明、初始化2.2 基于数组创建切片2.2 切片的长度(len)和容…

ESP32自动下载电路分享

下面是一个ESP32系列或者ESP8266等电路的一个自动下载电路 在ESP32等模块需要烧写程序的时候,需要通过将EN引脚更改为低电平并将IO0引脚设置为低电平来切换到烧写模式。 有时候也会采用先将IO接到一个按键上,按住按键拉低IO0的同时重新上电的方式进入烧写…

【OceanBase】使用 Superset 连接 OceanBase 数据库并进行数据可视化分析

文章目录 前言一、前提条件二、操作步骤2.1 准备云主机实例2.2 安装docker-compose2.3 使用docker-compose安装Superset2.3.1 克隆 Superset 的 GitHub 存储库2.3.2 通过 Docker Compose 启动 Superset 2.4 开通 OB Cloud 云数据库2.5 获取连接串2.6 使用 Superset 连接 OceanB…

联发科MTK6771/MT6771安卓核心板规格参数介绍

MT6771,也被称为Helio P60,是联发科技(MediaTek)推出的一款中央处理器(CPU)芯片,可运行 android9.0 操作系统的 4G AI 安卓智能模块。MT6771芯片采用了12纳米工艺制造,拥有八个ARM Cortex-A73和Cortex-A53核心,主频分别…

修复 ITunes 在 Windows 或 Mac 上不断崩溃的问题 [100% 有效]

对于 iDevice 用户来说,只能通过 iTunes 在 iDevice 和计算机之间传输文件的困境一直是一个紧迫的问题。所有 iPhone 用户可能都知道,iTunes 并不是一款高效的应用程序,有时性能会很差,例如在 iDevices 和计算机之间传输文件时不断…

【AI大模型】深入GPT-2模型细节:揭秘其卓越性能的秘密

目录 🍔 GPT2的架构 🍔 GPT2模型的细节 2.1 模型过程 2.2 GPT2工作细节探究 🍔 小结 学习目标 掌握GPT2的架构掌握GPT2的训练任务和模型细节 🍔 GPT2的架构 从模型架构上看, GPT2并没有特别新颖的架构, 它和只带有解码器模块…

C语言 - 理解函数栈帧

一:概述 函数栈帧是函数调用过程中为管理和存储函数相关信息(如局部变量、返回地址等)而在栈上分配的一块内存区域。它是实现函数调用、递归和返回的关键机制。 二:栈帧的组成 一个典型的栈帧通常包含以下内容(从高地…

windows终端conda activate命令行不显示环境名

问题: 始终不显示环境名 解决 首先需要配置conda的环境变量 确保conda --version能显示版本 然后对cmd进行初始化,如果用的是vscode中的终端,那需要对powershell进行初始化 Windows CMD conda init cmd.exeWindows PowerShell conda …

检索增强生成 和思维链 结合: 如何创建检索增强思维链 (RAT)?

论文地址:https://arxiv.org/pdf/2403.05313 Github地址:https://github.com/CraftJarvis/RAT 想象一下,一个人工智能助手可以像莎士比亚一样写作,像专家一样推理。这听起来很了不起,对吧?但是&#xff0…

Fabric链码部署测试

参考链接:运行 Fabric 应用程序 — Hyperledger Fabric Docs 主文档 (hyperledger-fabric.readthedocs.io) (2)fabric2.4.3部署运行自己的链码 - 知乎 (zhihu.com) Fabric2.0测试网络部署链码 - 辉哥哥~ - 博客园 (cnblogs.com) 1.启动测试…

如何单独安装 MATLAB 工具箱

很多时候由于 MATLAB 太大而选择安装一些 Toolbox,但用着用着发现要用到某个没有安装的 Toolbox,这时候就需要再单独安装这个 Toolbox,下面提供两种方法。 本文以安装 系统辨识工具箱 System Identification Toolbox 为例。 方法一&#xf…

Anaconda/Pytorch/PyCharm/Jupyter安装及使用

1.ANACONDA安装 Anaconda 是全球领先的数据科学与机器学习平台,专为开发者、数据分析师设计。通过 Anaconda,您可以轻松管理数据环境、安装依赖包,快速启动数据分析、机器学习项目。 丰富的 Python 数据科学库:Anaconda 集成了常…

RocketMQ消费者如何消费消息以及ack

1.前言 此文章是在儒猿课程中的学习笔记,感兴趣的想看原来的课程可以去咨询儒猿课堂 这篇文章紧挨着上一篇博客来进行编写,有些不清楚的可以看下上一篇博客: https://blog.csdn.net/u013127325/article/details/144934073 2.broker是如何…

【Logstash02】企业级日志分析系统ELK之Logstash 输入 Input 插件

Logstash 使用 Logstash 命令 官方文档 https://www.elastic.co/guide/en/logstash/current/first-event.html #各种插件 https://www.elastic.co/guide/en/logstash/current/input-plugins.html https://www.elastic.co/guide/en/logstash/current/filter-plugins.html htt…

【设计模式】 基本原则、设计模式分类

设计模式 设计模式是软件工程中的一种通用术语,指的是针对特定问题的经过实践验证的解决方案。设计模式并不是最终的代码实现,而是描述了如何解决某一类问题的思路和方法。 如果熟悉了设计模式,当遇到类似的场景,我们可以快速地…

【AI学习】Transformer深入学习(二):从MHA、MQA、GQA到MLA

前面文章: 《Transformer深入学习(一):Sinusoidal位置编码的精妙》 一、MHA、MQA、GQA 为了降低KV cache,MQA、GQA作为MHA的变体,很容易理解。 多头注意力(MHA): 多头注…

【DevOps】Jenkins部署

Jenkins部署 文章目录 Jenkins部署资源列表基础环境一、部署Gilab1.1、安装Gitlab1.2、修改配置文件1.3、加载配置文件1.4、访问Gitlab1.5、修改root登录密码1.6、创建demo测试项目1.7、上传代码1.8、验证上传的代码 二、部署Jenkins所需软件2.1、部署JDK2.2、部署Tomcat2.3、部…

Node.js - 文件操作

1. 文件写入 文件写入是计算机非常常见的操作,下载文件,安装软件,保存程序日志,视频录制等都使用到了 1.1 异步写入 const fs require("fs");// 写入文件 fs.writeFile(./sentence.txt, "Hello world", e…