Java8实战-总结33

news2025/1/12 9:43:13

Java8实战-总结33

  • 重构、测试和调试
    • 使用 Lambda 重构面向对象的设计模式
      • 策略模式
      • 模板方法

重构、测试和调试

使用 Lambda 重构面向对象的设计模式

新的语言特性常常让现存的编程模式或设计黯然失色。比如, Java 5中引入了for-each循环,由于它的稳健性和简洁性,已经替代了很多显式使用迭代器的情形。Java 7中推出的菱形操作符(<>)让大家在创建实例时无需显式使用泛型,一定程度上推动了Java程序员们采用类型接口(type interface)进行程序设计。

对设计经验的归纳总结被称为设计模式。设计软件时,可以复用这些方式方法来解决一些常见问题。这看起来像传统建筑工程师的工作方式,对典型的场景(比如悬挂桥、拱桥等)都定义有可重用的解决方案。例如,访问者模式常用于分离程序的算法和它的操作对象。单例模式一般用于限制类的实例化,仅生成一份对象。

Lambda表达式为程序员的工具箱又新添了一件利器。它们为解决传统设计模式所面对的问题提供了新的解决方案,不但如此,采用这些方案往往更高效、更简单。使用Lambda表达式后,很多现存的略显臃肿的面向对象设计模式能够用更精简的方式实现了。下面会针对五个设计模式展开讨论,分别是:

  • 策略模式
  • 模板方法
  • 观察者模式
  • 责任链模式
  • 工厂模式

策略模式

策略模式代表了解决一类算法的通用解决方案,可以在运行时选择使用哪种方案。例如使用不同的条件(比如苹果的重量,或者颜色)来筛选库存中的苹果。可以将这一模式应用到更广泛的领域,比如使用不同的标准来验证输入的有效性,使用不同的方式来分析或者格式化输入。
策略模式包含三部分内容:

  • 一个代表某个算法的接口(它是策略模式的接口)。
  • 一个或多个该接口的具体实现,它们代表了算法的多种实现(比如,实体类ConcreteStrategyA或者ConcreteStrategyB)。
  • 一个或多个使用策略对象的客户。
    在这里插入图片描述
    假设希望验证输入的内容是否根据标准进行了恰当的格式化(比如只包含小写字母或数字)。可以从定义一个验证文本(以String的形式表示)的接口入手:
public interface ValidationStrategy { 
 boolean execute(String s); 
} 

其次,定义了该接口的一个或多个具体实现:

public class IsAllLowerCase implements ValidationStrategy { 
	 public boolean execute(String s) { 
	 	return s.matches("[a-z]+"); 
	 } 
} 
public class IsNumeric implements ValidationStrategy { 
	public boolean execute(String s) { 
 		return s.matches("\\d+"); 
 	} 
} 

之后,就可以在程序中使用这些略有差异的验证策略了:

public class Validator { 
	private final ValidationStrategy strategy; 
	
	public Validator(ValidationStrategy v) { 
		this.strategy = v;
	} 
	
	public boolean validate(String s) { 
		return strategy.execute(s); 
	} 
} 

Validator numericValidator = new Validator(new IsNumeric()); 
boolean b1 = numericValidator.validate("aaaa");  //返回false
Validator lowerCaseValidator = new Validator(new IsAllLowerCase()); 
boolean b2 = lowerCaseValidator.validate("bbbb");  //返回true

使用Lambda表达式
ValidationStrategy是一个函数接口(除此之外,它还与Predicate<String>具有同样的函数描述)。这意味着不需要声明新的类来实现不同的策略,通过直接传递Lambda表达式就能达到同样的目的,并且还更简洁:

Validator numericValidator = new Validator((String s) -> s.matches("[a-z]+")); 
boolean b1 = numericValidator.validate("aaaa");  //直接传递Lambda表达式
Validator lowerCaseValidator = new Validator((String s) -> s.matches("\\d+"));  //直接传递Lambda表达式
boolean b2 = lowerCaseValidator.validate("bbbb"); 

Lambda表达式避免了采用策略设计模式时僵化的模板代码。如果仔细分析一下个中缘由,会发现,Lambda表达式实际已经对部分代码(或策略)进行了封装,而这就是创建策略设计模式的初衷。因此,建议对类似的问题,应该尽量使用Lambda表达式来解决。

模板方法

如果需要采用某个算法的框架,同时又希望有一定的灵活度,能对它的某些部分进行改进,那么采用模板方法设计模式是比较通用的方案。换句话说,模板方法模式在你“希望使用这个算法,但是需要对其中的某些行进行改进,才能达到希望的效果”时是非常有用的。

从一个例子着手,看看这个模式是如何工作的。假设需要编写一个简单的在线银行应用。通常,用户需要输入一个用户账户,之后应用才能从银行的数据库中得到用户的详细信息,最终完成一些让用户满意的操作。不同分行的在线银行应用让客户满意的方式可能还略有不同,比如给客户的账户发放红利,或者仅仅是少发送一些推广文件。可能通过下面的抽象类方式来实现在线银行应用:

abstract class OnlineBanking { 
	public void processCustomer(int id){ 
		Customer c = Database.getCustomerWithId(id); 
		makeCustomerHappy(c); 
 	}
	
	abstract void makeCustomerHappy(Customer c); 
} 

processCustomer方法搭建了在线银行算法的框架:获取客户提供的ID,然后提供服务让用户满意。不同的支行可以通过继承OnlineBanking类,对该方法提供差异化的实现。

使用Lambda表达式
使用Lambda表达式同样也可以解决这些问题(创建算法框架,让具体的实现插入某些部分)。你想要插入的不同算法组件可以通过Lambda表达式或者方法引用的方式实现。

这里向processCustomer方法引入了第二个参数,它是一个Consumer<Customer>类型的参数,与前文定义的makeCustomerHappy的特征保持一致:

public void processCustomer(int id, Consumer<Customer> makeCustomerHappy) { 
	Customer c = Database.getCustomerWithId(id); 
	makeCustomerHappy.accept(c); 
} 

现在,可以很方便地通过传递Lambda表达式,直接插入不同的行为,不再需要继承OnlineBanking类了:

new OnlineBankingLambda().processCustomer(1337, (Customer c) -> System.out.println("Hello " + c.getName()); 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云端IDE的技术选型1

背景 考虑到以下几点&#xff0c;准备给低代码平台开发一套云端的IDE&#xff1a; 桌面端IDE&#xff1a;vs code 或 idea&#xff0c;都有需要开发人员安装ide&#xff0c;以及配置环境很多时候&#xff0c;配置开发环境是个非常曲折过程&#xff0c;经常出现版本不匹配&…

基于TensorFlow+CNN+协同过滤算法的智能电影推荐系统——深度学习算法应用(含微信小程序、ipynb工程源码)+MovieLens数据集(五)

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 模型训练1&#xff09;数据集分析2&#xff09;数据预处理3&#xff09;模型创建4&#xff09;模型训练5&#xff09;获取特征矩阵 2. 后端Django1&#xff09;路由文件2&#xff09;视图层文件3&#xff09;项目…

GitHub上标星23K+的Redis进阶笔记(应用+原理+集群+拓展+源码)

先来看几道Redis面试题&#xff1a; redis为什么是key&#xff0c;value的&#xff0c;为什么不是支持SQL的&#xff1f;redis是多线程还是单线程&#xff1f;&#xff08;回答单线程的请回吧&#xff0c;为什么请回&#xff0c;请往下看&#xff09;redis的持久化开启了RDB和…

9.25day5---Qt

登录页面设计&#xff0c;建立用户注册以及登录的数据库&#xff0c;数据库保存用户名和密码 &#xff08;ps:本篇只完成了登录功能&#xff0c;其他功能&#xff0c;请见下篇嘿嘿。&#xff09; 再次注册则失败&#xff1a; 代码如下&#xff1a; 头文件&#xff1a; 登录…

Android字体大小dp,sp,px系统设置字体大小变化表现

Android字体大小dp,sp,px系统设置字体大小变化表现 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"andr…

14基于MATLAB的鲸鱼优化VMD参数,以熵值为适应度函数,对VMD参数惩罚因子和层数进行寻优,确定最优值并进行信号分解,程序已调通,可以直接运行。

基于MATLAB的鲸鱼优化VMD参数&#xff0c;以熵值为适应度函数&#xff0c;对VMD参数惩罚因子和层数进行寻优&#xff0c;确定最优值并进行信号分解&#xff0c;程序已调通&#xff0c;可以直接运行。

Idea操作Git合并另一个分支的部分提交

现有master、dev两个分支&#xff0c;master有提交1、2、3、4、5、6、7&#xff0c;dev是从master提交的3拉出来的分支&#xff08;Reset Current Branch to Here…&#xff0c;Mixed模式&#xff09;&#xff0c;有提交1、2、3&#xff0c;现在的需求是dev分支只需要合并maste…

解释器风格架构C# 代码

/*解释器风格架构是一种基于组件的设计架构&#xff0c;它将应用程序分解为一系列组件&#xff0c;每个组件负责处理特定的任务。这种架构有助于提高代码的可维护性和可扩展性。以下是如何使用C#实现解释器风格架构的步骤&#xff1a;定义组件&#xff1a;首先&#xff0c;定义…

10.2servlet基础2

一.SmartTomcat 1.第一次使用需要进行配置. 二.异常处理 1.404:浏览器访问的资源,在服务器上不存在. a.检查请求的路径和服务器配置的是否一致(大小写,空格,标点符号). b. 确认webapp是否被正确加载(检查web.xml没有/目录错误/内容错误/名字拼写错误)(多多关注日志信息). 2…

v-md-editor踩坑记

1、prismjs is not a function Vue3vite。在vueprees主题中&#xff0c;安装扩展代码高亮语音包运行失败。 解决方案&#xff1a; 查看下载好的本地包&#xff0c;尝试解构使用&#xff0c;执行成功 import { defineConfig } from vite import vue from vitejs/plugin-vue …

Vue系列(四)之 Vue路由介绍和Node.js的环境搭建

目录 一. Vue路由 1.1 Vue路由是什么 1.2 SPA是什么 1.3 Vue路由的使用步骤 二. Node.js环境搭建 2.1 Node.js是什么 2.2 npm是什么 2.3 Node.js环境搭建 1. 下载Node.js 2. 解压 3. 配置环境变量 4. 配置npm全局模块路径和cache默认安装位置 5. 修改npm镜像提高下…

蓝桥杯每日一题2023.9.12

3491. 完全平方数 - AcWing题库 题目描述 分析 完全平方数的一个特点&#xff1a; 所有的质因子的个数为偶数。eg1.9的质因子为3&#xff0c;3的个数为2&#xff0c;得到了9&#xff08;3*39&#xff09; eg2.81的质因子为3&#xff0c;3的个数为4&#xff0c;得到81&#…

安卓逆向 - EdXposed LSPosed VirtualXposed

一、引言 接上篇&#xff1a;安卓逆向 - Xposed入门教程_小馒头yy的博客-CSDN博客 我们介绍了Xposed入门安装使用&#xff0c;但是只支持到Android 8&#xff0c;并且安装模块需要重启。今天我们来看看Xposed的其他版本。 二、各种Xposed框架对比 1、Xposed 只支持到安卓8&…

python+django美食菜谱分享网站系统平台

开发语言&#xff1a;Python 框架&#xff1a;django/flask Python版本&#xff1a;python3.7.7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;PyCharm .本系统采用了nodejs语言的vue框架&#xff0c;数据采用MySQL数据库进行存储。结合B/S结…

【数据结构】哈希表(详)

文章目录 前言正文一、基本概念二、基本原理1.哈希函数1.1直接定址法&#xff08;常用&#xff09;1.2除留余数法&#xff08;常用&#xff09;1.3 平方取中法&#xff08;了解&#xff09;1.4 折叠法(了解)1.5 随机数法(了解)1.6数学分析法(了解) 2.哈希冲突2.1 平均查找长度2…

第八天:gec6818arm开发板和Ubuntu中安装并且编译移植mysql驱动连接QT执行程序

一、Ubuntu18.04中安装并且编译移植mysql驱动程序连接qt执行程序 1 、安装Mysql sudo apt-get install mysql-serverapt-get isntall mysql-clientsudo apt-get install libmysqlclient-d2、查看是否安装成功&#xff0c;即查看MySQL版本 mysql --version 3、MySQL启动…

中秋节听夜曲,Android OpenGL 呈现周董专属的玉兔主题音乐播放器

概述 前几天发现QQ音乐有个好玩的功能&#xff0c;为用户提供了多种 播放器主题&#xff0c;其中 原神 的主题让我眼前一亮&#xff1a; 当然&#xff0c;诸如 换肤、主题 类的功能已经屡见不鲜&#xff0c;但这类沉浸式播放器的听歌体验确实不错。 见猎心喜&#xff0c;正好…

FPGA千兆网 UDP 网络视频传输,基于88E1518 PHY实现,提供工程和QT上位机源码加技术支持

目录 1、前言版本更新说明免责声明 2、我这里已有的以太网方案3、设计思路框架视频源选择OV5640摄像头配置及采集动态彩条UDP协议栈UDP视频数据组包UDP协议栈数据发送UDP协议栈数据缓冲IP地址、端口号的修改Tri Mode Ethernet MAC介绍以及移植注意事项88E1518 PHYQT上位机和源码…

人工智能AI 全栈体系(五)

第一章 神经网络是如何实现的 为什么使用 ReLu 函数&#xff1f; 五、梯度消失问题 1. 什么是梯度消失问题&#xff1f; 前面我们介绍的 BP 算法中&#xff0c;是这样更新权重值的&#xff1a; δ ∗ h o h ( 1 − o h ) ∑ ∗ k ∈ 后续 ( h ) δ ∗ k w ∗ k h \delta*h …

基于Python+Flask实现一个简易网页验证码登录系统案例

在当今的互联网世界中&#xff0c;为了防止恶意访问&#xff0c;许多网站在登录和注册表单中都采用了验证码技术。验证码可以防止机器人自动提交表单&#xff0c;确保提交行为背后有一个真实的人类用户。 本文将向您展示如何使用Python的Flask框架来创建一个简单的验证码登录系…