Java设计模式:一、六大设计原则-05:接口隔离原则
文章目录
- 一、定义:接口隔离原则
- 二、模拟场景:接口隔离原则
- 三、违背方案:接口隔离原则
- 3.1 工程结构
- 3.2 英雄技能调用
- 3.2.1 英雄技能接口
- 3.2.2 英雄:后裔
- 3.2.3 英雄:廉颇
- 3.3 单元测试
- 四、改善代码:接口隔离原则
- 4.1 工程结构
- 4.2 英雄分配英雄技能
- 4.2.1 射箭接口
- 4.2.2 隐袭接口
- 4.2.3 沉默
- 4.2.4 晕眩
- 4.2.5 英雄后裔的实现
- 4.2.6 英雄廉颇的实现
- 4.3 单元测试
一、定义:接口隔离原则
- 接口隔离原则:
Interface Segregation Principle,ISP。- 客户端不应该被迫依赖于它不使用的方法。
- 另一个定义:一个类对另一个类的依赖应该建立在最小的接口上。
- 接口隔离原则要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口只包含客户感兴趣的方法。
- 接口隔离是为了 高内聚、低耦合。
- 在实际的业务开发中,通常会先定义好需要开发的接口,并由各个服务类实现。
- 但如果没有经过考虑和设计,就很可能造成一个接口中包括众多的接口方法,而这些接口并不一定在每一个类中都需要实现。
- 这样的接口很难维护,也不易于扩展,每一次修改验证都有潜在的风险。
- 在具体应用接口隔离原则时,应该根据一下几个规则衡量。
- 接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。
- 为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
- 了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同,要深入了解业务逻辑。
- 提高内聚,减少对外交互。让接口用最少的方法完成最多的事情。
二、模拟场景:接口隔离原则
- 《王者荣耀》里有很多英雄,可以分为射手、战士、刺客等,每个英雄有三种技能。
- 这些技能该如何定义,让每个英雄实现相应的技能效果呢?
三、违背方案:接口隔离原则
3.1 工程结构
design-1.5-0
|——src|——main|--java|--com.lino.design|--HeroHouYi.java|--HeroLianPo.java|--ISkill.java|——test|--java|--com.lino.design.test|--ApiTest.java
3.2 英雄技能调用
3.2.1 英雄技能接口
ISkill.java
package com.lino.design;/*** @description: 英雄技能接口*/
public interface ISkill {/*** 射箭*/void doArchery();/*** 隐袭*/void doInvisible();/*** 沉默*/void doSilent();/*** 眩晕*/void doVertigo();
}
- 定义一个技能接口,实现的英雄都需要实现这个接口,进而实现自己的技能。
- 这里提供了四个技能的接口,包括射箭、隐袭、沉默、晕眩,每个英雄都实现这个接口。接下来实现两个英雄:后裔和廉颇。
3.2.2 英雄:后裔
HeroHouYi.java
package com.lino.design;/*** @description: 英雄:后裔*/
public class HeroHouYi implements ISkill {@Overridepublic void doArchery() {System.out.println("后裔的灼日之矢");}@Overridepublic void doInvisible() {System.out.println("后裔的隐身技能");}@Overridepublic void doSilent() {System.out.println("后裔的沉默技能");}@Overridepublic void doVertigo() {// 无此技能的实现}
}
- 在英雄后裔的类中,实现了三个技能,最后一个晕眩的技能是不需要实现的。
3.2.3 英雄:廉颇
HeroLianPo.java
package com.lino.design;/*** @description: 英雄:廉颇*/
public class HeroLianPo implements ISkill {@Overridepublic void doArchery() {// 无此技能的实现}@Overridepublic void doInvisible() {System.out.println("廉颇的隐身技能");}@Overridepublic void doSilent() {System.out.println("廉颇的沉默技能");}@Overridepublic void doVertigo() {System.out.println("廉颇的眩晕技能");}
}
- 在英雄廉颇的类中,同样只实现了三个技能,有一个射箭的技能没有实现。
3.3 单元测试
ApiTest.java
@Test
public void test_ISKill() {// 后裔HeroHouYi heroHouYi = new HeroHouYi();heroHouYi.doArchery();// 廉颇HeroLianPo heroLianPo = new HeroLianPo();heroLianPo.doInvisible();
}
测试结果
后裔的灼日之矢
廉颇的隐身技能
- 综上,每个英雄的实现类里都有一个和自己无关的接口实现类,非常不符合设计模式,也不易于维护。
- 因为不仅无法控制外部的调用,还需要维护对应的文档,来说明这个接口不需要实现。如果由更多这样的接口,就会变得非常麻烦。
四、改善代码:接口隔离原则
4.1 工程结构
design-1.5-1
|——src|——main|--java|--com.lino.design|--impl| |-HeroHouYi.java| |-HeroLianPo.java|--ISkillArchery.java|--ISkillInvisible.java|--ISkillSilent.java|--ISkillVertigo.java|——test|--java|--com.lino.design.test|--ApiTest.java
4.2 英雄分配英雄技能
- 按照接口隔离原则的约定,应该在确保合理的情况下,把接口细分。保证一个松散的结构,也就是把技能拆分出来,每个英雄都可以按需继承实现。
- 接下来分别定义四个技能接口,包括:
- 射箭:
ISkillArchery - 隐身:
ISkillInvisible - 沉默:
ISkillSilent - 晕眩:
ISkillVertigo
- 射箭:
4.2.1 射箭接口
ISkillArchery.java
package com.lino.design;/*** @description: 射箭技能*/
public interface ISkillArchery {/*** 射箭*/void doArchery();
}
4.2.2 隐袭接口
ISkillInvisible.java
package com.lino.design;/*** @description: 影袭技能*/
public interface ISkillInvisible {/*** 隐袭*/void doInvisible();
}
4.2.3 沉默
ISkillSilent.java
package com.lino.design;/*** @description: 沉默技能*/
public interface ISkillSilent {/*** 沉默*/void doSilent();
}
4.2.4 晕眩
ISkillSilent.java
package com.lino.design;/*** @description: 晕眩技能*/
public interface ISkillVertigo {/*** 眩晕*/void doVertigo();
}
4.2.5 英雄后裔的实现
HeroHouYi.java
package com.lino.design.impl;import com.lino.design.ISkillArchery;
import com.lino.design.ISkillInvisible;
import com.lino.design.ISkillSilent;/*** @description: 英雄:后裔*/
public class HeroHouYi implements ISkillArchery, ISkillInvisible, ISkillSilent {@Overridepublic void doArchery() {System.out.println("后裔的灼日之矢");}@Overridepublic void doInvisible() {System.out.println("后裔的隐身技能");}@Overridepublic void doSilent() {System.out.println("后裔的沉默技能");}
}
4.2.6 英雄廉颇的实现
HeroLianPo.java
package com.lino.design.impl;import com.lino.design.ISkillInvisible;
import com.lino.design.ISkillSilent;
import com.lino.design.ISkillVertigo;/*** @description: 英雄:廉颇*/
public class HeroLianPo implements ISkillInvisible, ISkillSilent, ISkillVertigo {@Overridepublic void doInvisible() {System.out.println("廉颇的隐身技能");}@Overridepublic void doSilent() {System.out.println("廉颇的沉默技能");}@Overridepublic void doVertigo() {System.out.println("廉颇的眩晕技能");}
}
4.3 单元测试
ApiTest.java
@Test
public void test_ISKill() {// 后裔HeroHouYi heroHouYi = new HeroHouYi();heroHouYi.doArchery();// 廉颇HeroLianPo heroLianPo = new HeroLianPo();heroLianPo.doInvisible();
}
测试结果
后裔的灼日之矢
廉颇的隐身技能
- 现在可以看到这两个英雄的类都按需实现了自己需要的技能接口。
- 这样的实现方式就可以避免一些本身不属于自己的技能还需要不断地用文档的方式进行维护,同时提高了代码的可靠性,在别人接手或者修改时,可以降低开发成本和维护风险。
相关文章:
Java设计模式:一、六大设计原则-05:接口隔离原则
文章目录 一、定义:接口隔离原则二、模拟场景:接口隔离原则三、违背方案:接口隔离原则3.1 工程结构3.2 英雄技能调用3.2.1 英雄技能接口3.2.2 英雄:后裔3.2.3 英雄:廉颇 3.3 单元测试 四、改善代码:接口隔离…...
第63步 深度学习图像识别:多分类建模误判病例分析(Tensorflow)
基于WIN10的64位系统演示 一、写在前面 上两期我们基于TensorFlow和Pytorch环境做了图像识别的多分类任务建模。这一期我们做误判病例分析,分两节介绍,分别基于TensorFlow和Pytorch环境的建模和分析。 本期以健康组、肺结核组、COVID-19组、细菌性&am…...
OpenCv读/写视频色差 方案
OpenCv read / write video color differenceOpenCv读/写视频色差 感谢博主: OpenCv读/写视频色差答案 - 爱码网 有没有办法让 OpenCV 使用正确的转换?? 是的,使用 GStreamer 后端而不是 FFmpeg 后端,颜色看起来很完…...
【传输层】网络基础 -- UDP协议 | TCP协议
再谈端口号端口号范围划分netstatpidof UDPUDP的特点面向数据报UDP的缓冲区 基于UDP的应用层协议 TCP认识TCP协议的报头理解封装解包理解可靠性TCP工作模式16位窗口大小6位标志位URGACKPSHRSTSYNFIN 再谈端口号 端口号(Port)标识了一个主机上进行通信的不同的应用程序 在TCP/I…...
Android开发之性能测试工具Profiler
前言 性能优化问题,在我们开发时都会遇到,但是在小厂和对自己要求不严格的情况下,我都很少去做性能优化; 在性能优化上,基本大家都是通过自己的开发经验和性能分析工具来发现问题,今天给大家分享一下小编最…...
SpringBoot初级开发--多环境配置的集成(9)
在Springboot的开发中,我们经常要切换各种各样的环境配置,比如现在是开发环境,然后又切换到生产环境,这个时候用多环境配置就是一个明智的选择。接下来我们沿用上一章的工程来配置多环境配置工程。 1.准备多环境配置文件 这里我…...
(数学) 剑指 Offer 39. 数组中出现次数超过一半的数字 ——【Leetcode每日一题】
❓ 剑指 Offer 39. 数组中出现次数超过一半的数字 难度:简单 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输…...
如何用PS把roughness贴图转换成Smoothness,并放入Metallic贴图的a通道。
1:用PS打开Roughness贴图 2:选择反相,装换成Smoothness贴图 3:新建一个大小相等的psd文件,或者打开Metallic贴图 4:如果没有金属度贴图,就把新建的图画成纯黑色 5:选择图层蒙版->…...
了解XSS攻击与CSRF攻击
什么是XSS攻击 XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的网络安全漏洞,它允许攻击者在受害者的浏览器上执行恶意脚本。这种攻击通常发生在 web 应用程序中,攻击者通过注入恶意脚本来利用用户对网站的信任&…...
安全测试-django防御安全策略
django安全性 django针对安全方面有一些处理,学习如何进行处理设置,也有利于学习安全测试知识。 CSRF 跨站点请求伪造(Cross-Site Request Forgery,CSRF)是一种网络攻击方式,攻击者欺骗用户在自己访问的网…...
7.react useReducer使用与常见问题
useReducer函数 1. useState的替代方案.接收一个(state, action)>newState的reducer, 并返回当前的state以及与其配套的dispatch方法2. 在某些场景下,useReducer会比useState更加适用,例如state逻辑较为复杂, 且**包含多个子值**,或者下一个state依赖于之前的state等清楚us…...
c#泛型(generic)
概述: C#中的泛型(Generics)是一种允许在编写类、方法和委托时使用参数化类型的机制。泛型允许我们编写更通用、可重用的代码,可以避免类型转换和重复编写类似的代码。 泛型的基本语法如下所示: class ClassName<…...
【力扣每日一题】2023.8.30 到家的最少跳跃次数
目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 题目给我们一只跳蚤,我们可以操控它前跳 a 格或是后跳 b 格,不能跳到小于0的位置,有一些被禁止的点不…...
精读《算法题 - 地下城游戏》
今天我们看一道 leetcode hard 难度题目:地下城游戏。 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士…...
随记-Kibana Dev Tools,ES 增删改查 索引,Document
索引 创建索引 创建索引 PUT index_test创建索引 并 修改分片信息 # 创建索引 并 修改分片信息 PUT index_test2 { # 必须换行, PUT XXX 必须独占一行,类似的 其他请求也需要独占一行 "settings": {"number_of_shards": 1, # 主分片"…...
什么是架构,架构的本质是什么
不论是开发人员还是架构师,我们都一直在跟软件系统打交道,架构是在工作中出现最频繁的术语之一。那么,到底什么是架构?你可能有自己的答案,也有可能没有答案。对“架构”的理解需要我们不断在实践中思考、归纳、演绎&a…...
Python爬虫(十七)_糗事百科案例
糗事百科实例 爬取糗事百科段子,假设页面的URL是: http://www.qiushibaike.com/8hr/page/1 要求: 使用requests获取页面信息,用XPath/re做数据提取获取每个帖子里的用户头像连接、用户姓名、段子内容、点赞次数和评论次数保存到json文件内…...
Ae 效果:CC Threads
生成/CC Threads Generate/CC Threads CC Threads(CC 编织条)效果基于当前图层像素生成编织条图案和纹理。可以用在各种设计中,如背景设计、图形设计、文字设计等。 ◆ ◆ ◆ 效果属性说明 Width 宽度 设置编织的宽度。 默认值为 50。值越大…...
Kotlin 协程 - 多路复用 select()
一、概念 又叫选择表达式,是一个挂起函数,可以同时等待多个挂起结果,只取用最快恢复的那个值(即多种方式获取数据,哪个更快返回结果就用哪个)。 同时到达 select() 会优先选择先写子表达式,想随…...
学习笔记-ThreadLocal
ThreadLocal 什么是ThreadLocal? ThreadLocal 是线程本地变量类,在多线程并行执行过程中,将变量存储在ThreadLocal中,每个线程中都有独立的变量,因此不会出现线程安全问题。 应用举例 解决线程安全问题:例…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
