当前位置: 首页 > news >正文

Java8实战 - 行为参数化传递代码

背景:

根据《java8实战》把第二章简单概括一下。

在软件工程中,一个最重要的问题是,用户的需求会一直变化,如何应对不断变化的需求,并且把工作量降到最低是需要考虑的,而行为参数化就是一个处理频繁变更需求的软件开发模式。

在我看来,行为参数化,是拿出一块代码段,准备好却不去执行,这个代码块会被其他部分调用,意味着可以推迟这个代码的执行。

下面用在库存中筛选苹果的案例来说明。

第一版:筛选绿苹果

public static List<Apple> filterGreenApples(List<Apple> inventory) {List<Apple> result = new ArrayList<>();for(Apple app: inventory) {if("green".equals(apple.getColor())) {result.add(apple);}}return result;
}

上面的代码可以就是筛选绿色苹果,但是如果现在需求变了,需要筛选红色苹果,那么第一反应是在上面的函数入参中,加入颜色条件来匹配。

第二版:颜色作为参数

public static List<Apple> filterGreenApples(List<Apple> inventory, String color) {List<Apple> result = new ArrayList<>();for(Apple app: inventory) {if(apple.getColor().equals(color)) {result.add(apple);}}return result;
}
List<Apple> greenApples = filterAppleByColor(Inventory, "green");
List<Apple> greenApples = filterAppleByColor(Inventory, "red");

这样可以得到最终答案,但是又出现了一个问题,现在需求变成需要能区分轻苹果和重苹果.

于是把上面代码拷贝一份又写了个针对重量的

第三版:重量作为参数

public static List<Apple> filterGreenApples(List<Apple> inventory, int weight) {List<Apple> result = new ArrayList<>();for(Apple app: inventory) {if(apple.getWeight() > weight) {result.add(apple);}}return result;
}

这样虽然可以,但是打破了DRY(Don't Repeat Yourself, 不要重复自己)软件工程原则,当然不重复情况下,还可以加上一个标志位来判断是对哪个条件进行查询,如下

第四版:颜色和重量统一查询函数

public static List<Apple> filterGreenApples(List<Apple> inventory, String color,int weight, boolean flag) {List<Apple> result = new ArrayList<>();for(Apple app: inventory) {if((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight)){result.add(apple);}}return result;
}

这样的代码可读性很差,并且标志位现在只是颜色和重量,如果再加查询条件,比如产地,形状等,就无法满足需求了.

行为参数化传递代码

考虑将选择的标准进行建模,比如绿色的吗,重量超过150克吗,来返回一个boolean值,这种返回boolean值函数称为”谓词“,定义一个接口来选择标准建模:

public interface ApplePredicate{boolean test(Apple apple);
}

那么就可以又很多实现类了,比如

public class AppleHeavyWeightPredicate implements ApplePredicate {public boolean test(Apple apple) {return apple.getWeight() > 150;}
}public class AppleGreenColorPredicate implements ApplePredicate {public boolean test(Apple apple) {return "green".equals(apple.getColor());}
}

把不同filter方法的不同行为封装起来,称为“策略”,然后再运行时选择一个算法,这个算法族就是applePredicate。

第五版:applePredicate改造后

public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {List<Apple> result = new ArrayList<>();for(Apple app: inventory) {if(p.test(apple)){result.add(apple);}}return result;
}

这样使用灵活多了,假设选择需求变了,组合条件,既要红苹果,又要重量超过150克,那么就再增加一个类实现ApplePredicate就行

public class AppleRedAndHeavyPredicate implements ApplePredicate {public boolean test(Apple apple) {return "red".equals(apple.getColor()) && apple.getWeight() > 150;}
}List<Apple> redAndHeavyApple = filterApples(inventory, new AppleRedAndHeavyPredicate());

 但是这样还不完美,因为现在filterApples入参都需要一个new一个过滤条件相关的对象,并且实现test方法,为了在进一步减少代码,还可以用匿名类和lambda表达式

第六版:匿名类

List<Apple> redAndHeavyApple = filterApples(inventory, new AppleRedAndHeavyPredicate() {public boolean test(Apple apple) {return "red".equals(apple.getColor());}
});

匿名类看起来减少了类的实现代码,但是调用时候还是塞了很多代码。那么就到了最后一个

第七版:Lambda表达式

List<Apple> redAndHeavyApple = filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor()));

这样看起来就干净多了。现在filterApples只是作用于苹果的筛选,我们甚至更进一步,造一个通用filter,用泛型来替代Apple,如下:

public interface Predicate<T> {boolean test(T t);
}public static <T> List<T> filter<List<T> list, Predicate<T> p> {List<T> result = new ArrayList<>();for(T e: list){if(p.test(e)){result.add(e);}        }
}

这样就可以把filter方法用在香蕉,桔子,等等上。这边的Predicate<T>是一个函数式的接口,为了缩短篇幅,会在下个博客讲

相关文章:

Java8实战 - 行为参数化传递代码

背景&#xff1a; 根据《java8实战》把第二章简单概括一下。 在软件工程中&#xff0c;一个最重要的问题是&#xff0c;用户的需求会一直变化&#xff0c;如何应对不断变化的需求&#xff0c;并且把工作量降到最低是需要考虑的&#xff0c;而行为参数化就是一个处理频繁变更需…...

jmeter,取“临时重定向的登录接口”响应头中的cookie

1、线程组--创建线程组&#xff1b; 2、线程组--添加--取样器--HTTP请求&#xff1b; 3、Http请求--添加--后置处理器--正则表达式提取器&#xff1b; 4、线程组--添加--监听器--查看结果树&#xff1b; 5、线程组--添加--取样器--调试取样器。 首先理解 自动重定向 与跟随…...

流程控制之条件判断

目录 流程控制之条件判断 2.1.if语句语法 2.1.1单分支结构 2.1.2双分支结构 2.1.3多分支结构 2.2.案例 例一: 例2: 例3: 例4: 例5: 例6: 例7: 例8: 例9: 2.3.case多条件判断 2.3.1.格式 2.3.2.执行过程 例10: 流程控制之条件判断 2.1.if语句语法 2.1.1单分…...

2 - Electron 核心概念

Electron 核心概念 主进程 通过Node.js、Electron提供的API与系统底层打交道启动项目时运行的 main.js 脚本就是我们说的主进程。在主进程运行的脚本可以以创建 Web 页面的形式展示 GUI。主进程只有一个 渲染进程 每个 Electron 的页面都在运行着自己的进程&#xff0c;这样…...

Cmake找不到mysql.h和libmysqlclient.so

查看mysql.h和libmysqlclient.so的路径 eikeik-Virtual-Machine:~/桌面/dbpool/bin$ locate mysql.h /usr/include/mysql/mysql.h eikeik-Virtual-Machine:~/桌面/dbpool/bin$ locate libmysqlclient.so /usr/lib/x86_64-linux-gnu/libmysqlclient.so /usr/lib/x86_64-linux-g…...

图论——二分图

图论——二分图 二分图通俗解释 有一个图&#xff0c;将顶点分成两类&#xff0c;边只存在不同类顶点之间&#xff0c;同类顶点之间设有边。称图 G 为二部图&#xff0c;或称二分图&#xff0c;也称欧图。 性质 二分图不含有奇数环图中没有奇数环&#xff0c;一定可以转换为二…...

国产浪潮服务器:风扇免手动调节脚本

简介&#xff1a;浪潮集团&#xff0c;是中国本土顶尖的大型IT企业之一&#xff0c;中国领先的云计算、大数据服务商。浪潮集团旗下拥有浪潮信息、浪潮软件、浪潮国际&#xff0c;业务涵盖云计算、大数据、工业互联网等新一代信息技术产业领域&#xff0c;为全球120多个国家和地…...

智能科技企业网站搭建的作用是什么

随着科学技术快速提升&#xff0c;各种智能产品随之而来&#xff0c;每个赛道里都涌入了大量企业商家&#xff0c;有些热门产品更是广受关注&#xff0c;对企业来说&#xff0c;形象、品牌、信息等方面需要完美呈现到用户眼前&#xff0c;而网站无疑是很好的工具。 企业通过【…...

【多组学数据驱动的机器学习:生物医学研究的创新与突破】

简介&#xff1a;随着生物医学研究的不断发展&#xff0c;多组学数据在疾病预防、诊断和治疗方面发挥着越来越重要的作用。本文将介绍如何利用机器学习技术对多组学数据进行综合分析&#xff0c;以及这种方法在生物医学研究中的优势和潜力。 正文&#xff1a; 一、多组学数据…...

AI影响谷歌正在推出新的人工智能模型,用于医疗保健。以下是医生如何使用它们的介绍

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

云仓酒庄带您品法国葡萄酒

说起葡萄酒肯定绕不开法国&#xff0c;法国葡萄酒闻名中外&#xff0c;口碑卓越。作为世界上的产酒大国&#xff0c;可以说是每一寸土地都可以种植葡萄。云仓酒庄的品牌雷盛红酒分享这么优秀的一个葡萄酒产酒国有哪些特点呢&#xff1f; 1.产区特色&#xff1a;波国有最著名的…...

XIAO ESP32S3之实现口罩检测

一、例程介绍 此例程是运行FOMO 轻量检测模型实现人员佩戴口罩检测&#xff0c;Demo中已包含训练好的模型参数&#xff0c;无需再训练。 FOMO(Faster Objects, More Objects) 是由 Edgeimpulse 工程师提出的一种轻量级的目标检测模型&#xff0c;其主要特点是模型非常小&#…...

LVS简介及LVS-NAT负载均衡群集的搭建

目录 LVS群集简介 群集的含义和应用场景 性能扩展方式 群集的分类 负载均衡&#xff08;LB&#xff09; 高可用&#xff08;HA&#xff09; 高性能运算&#xff08;HPC&#xff09; LVS的三种工作模式 NAT 地址转换 TUN IP隧道 IP Tunnel DR 直接路由 Direct Rout…...

ElasticSearch之cat segments API

命令样例如下&#xff1a; curl -X GET "https://localhost:9200/_cat/segments?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下&#xff1a; index shard prirep ip segment g…...

docker镜像与容器的迁移

docker容器迁移有两组命令&#xff0c;分别是 save & load &#xff1a;操作的是images&#xff0c; 所以要先把容器commit成镜像export & import&#xff1a;直接操作容器 我们先主要看看他们的区别&#xff1a; 一 把容器打包为镜像再迁移到其他服务器 如把mysq…...

Cmake基础(2)

使用一个简单的示例来应用cmake&#xff0c;无任何三方库的单一的应用程序项目 你可以收获 使用cmake生成VS项目生成mingw项目(makefile) 1 首先新建一个cpp&#xff0c;我们要做一个控制台应用程序 #include<iostream> void main(){std::cout<<"hello cm…...

OSPF理论总结与实验

第1章 OSPF[1] 本章阐述了OSPF协议的特征、术语&#xff0c;OSPF的路由器类型、网络类型、区域类型、LSA类型&#xff0c;OSPF报文的具体内容及作用&#xff0c;描述了OSPF的邻居关系&#xff0c;通过实例让读者掌握OSPF在各种场景中的配置。 本章包含以下内容&#xff1a; …...

浅谈安科瑞无线测温产品在巴西某工厂的应用

摘 要&#xff1a;高压开关设备是变电站和配电站中保证电力系统安全运行的重要设备之一,因此,开关柜的稳定运行对于整个电力系统有非常重要的意义。设备老化、长期高负荷运行都可能使设备局部温度过高而发生火灾&#xff0c;因此,对变电站内的敏感设备进行温度检测变得尤为重要…...

RabbitMQ 命令

Docker # 进入容器 > docker exec -it rabbitmq /bin/bash# 帮助 > rabbitmq-service help# 查看所有队列 > rabbitmqctl list_queues Windows 进入安装目录【D:\Program Files\RabbitMQ Server\rabbitmq_server-3.9.10\sbin】输入cmd # 帮助 > rabbitmq-servic…...

数据库系列之简要对比下GaussDB和OpenGauss数据库

GaussDB作为一款企业级的数据库产品&#xff0c;和开源数据库OpenGauss之间又是什么样的关系&#xff0c;刚开始接触的时候是一头雾水&#xff0c;因此本文简要对比下二者的区别&#xff0c;以加深了解。 1、GaussDB和OpenGauss数据库简要对比 GaussDB是华为基于PostgreSQL数据…...

终极矢量图标库完全指南:Remix Icon 3200+免费图标深度解析

终极矢量图标库完全指南&#xff1a;Remix Icon 3200免费图标深度解析 【免费下载链接】RemixIcon Open source neutral style icon system 项目地址: https://gitcode.com/gh_mirrors/re/RemixIcon Remix Icon 是一套开源的矢量图标库&#xff0c;包含超过3200个精心设…...

从原理图到PCB:手把手教你搞定PCIE X4接口的完整电路设计(附时钟、电源、热插拔信号详解)

从原理图到PCB&#xff1a;手把手教你搞定PCIE X4接口的完整电路设计 在高速数字电路设计中&#xff0c;PCIE接口因其出色的带宽和稳定性&#xff0c;已成为现代计算机系统中不可或缺的组成部分。无论是主板设计、显卡开发还是各类扩展卡&#xff0c;PCIE接口的正确实现直接关…...

Degrees of Lewdity 本地化实践指南

Degrees of Lewdity 本地化实践指南 Degrees of Lewdity 作为一款开源游戏&#xff0c;其本地化实践是打破语言壁垒、实现文化适配的关键环节。本文将从本地化价值定位、环境适配、执行蓝图、故障诊断、进阶优化到生态导航&#xff0c;为零基础用户提供一套完整的本地化技术方…...

基于Nuxt 4与Shadcn/ui的现代全栈仪表板开发实战

1. 项目概述&#xff1a;一个现代全栈仪表板的技术栈选择 最近在做一个内部管理后台&#xff0c;需要快速搭建一个既美观又功能齐全的仪表板。我的核心需求很明确&#xff1a;开发要快、代码质量要高、用户体验要好&#xff0c;并且要能轻松应对多语言场景。在评估了市面上各种…...

死锁四大必要条件解析

好的&#xff0c;针对“死锁考点与高频面试题”&#xff0c;我将直接进行核心内容解构与推演&#xff0c;并生成符合规范的答案。死锁是多线程并发编程中的核心难点与高频考点&#xff0c;其核心围绕定义、条件、场景、检测、预防与避免展开。一、 死锁核心定义与必要条件死锁是…...

Kaggle竞赛提分利器:如何用Stacking融合XGBoost、LightGBM和CatBoost模型?

Kaggle竞赛进阶指南&#xff1a;Stacking融合三大梯度提升树的实战策略 在Kaggle竞赛中&#xff0c;当单一模型的性能触及天花板时&#xff0c;模型融合技术往往成为突破瓶颈的关键。不同于教科书式的理论讲解&#xff0c;本文将聚焦竞赛实战中的核心痛点——如何通过Stacking技…...

硬件对齐的稀疏注意力机制:原理、优化与实践

1. 硬件对齐的稀疏注意力机制概述在自然语言处理领域&#xff0c;Transformer架构已成为主流&#xff0c;但其核心组件——注意力机制的计算复杂度随序列长度呈平方级增长&#xff0c;这成为处理长文本的主要瓶颈。传统全注意力(Full Attention)需要计算每个查询(Query)与所有键…...

图解UART串口通信:从电平标准到数据帧的完整解析

1. UART串口通信基础&#xff1a;从物理层到协议层 第一次接触嵌入式开发时&#xff0c;我被UART这个名字唬住了——Universal Asynchronous Receiver/Transmitter&#xff08;通用异步收发器&#xff09;&#xff0c;听起来像是某种高端设备。直到用USB转TTL模块点亮了第一个L…...

从基础到智能体:RAG技术演进与实战避坑指南

1. 从基础到进阶&#xff1a;我眼中的RAG技术演进与实战价值如果你正在探索如何让大语言模型&#xff08;LLM&#xff09;变得更“靠谱”&#xff0c;尤其是在处理专业、实时或私有数据时&#xff0c;那么“检索增强生成”&#xff08;RAG&#xff09;技术几乎是你绕不开的路径…...

抖音无水印下载器:终极免费批量下载工具完全指南

抖音无水印下载器&#xff1a;终极免费批量下载工具完全指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖…...