Java8实战-总结34

Java8实战-总结34

  • 重构、测试和调试
    • 使用 Lambda 重构面向对象的设计模式
      • 观察者模式
      • 责任链模式

重构、测试和调试

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

观察者模式

观察者模式是一种比较常见的方案,某些事件发生时(比如状态转变),如果一个对象(通常称之为主题)需要自动地通知其他多个对象(称为观察者),就会采用该方案。创建图形用户界面(GUI)程序时,经常会使用该设计模式。这种情况下,在图形用户界面组件(比如按钮)上注册一系列的观察者。如果点击按钮,观察者就会收到通知,并随即执行某个特定的行为。 但是观察者模式并不局限于图形用户界面。比如,观察者设计模式也适用于股票交易的情形,多个券商可能都希望对某一支股票价格(主题)的变动做出响应。下图通过UML图解释了观察者模式。
在这里插入图片描述
Twitter这样的应用设计并实现一个定制化的通知系统。想法很简单:好几家报纸机构,比如《纽约时报》《卫报》以及《世界报》都订阅了新闻,他们希望当接收的新闻中包含他们感兴趣的关键字时,能得到特别通知。首先,需要一个观察者接口,它将不同的观察者聚合在一起。它仅有一个名为notify的方法,一旦接收到一条新的新闻,该方法就会被调用:

interface Observer { void notify(String tweet); 
} 

现在,可以声明不同的观察者(比如,这里是三家不同的报纸机构),依据新闻中不同的关键字分别定义不同的行为:

class NYTimes implements Observer { public void notify(String tweet) { if(tweet != null && tweet.contains("money")) { System.out.println("Breaking news in NY! " + tweet); } } 
} class Guardian implements Observer { public void notify(String tweet) { if(tweet != null && tweet.contains("queen")) { System.out.println("Yet another news in London... " + tweet); } } 
} class LeMonde implements Observer { public void notify(String tweet) { if(tweet != null && tweet.contains("wine")) { System.out.println("Today cheese, wine and news! " + tweet); } } 
} 

最重要的部分是Subject,为它定义一个接口:

interface Subject { void registerObserver(Observer o); void notifyObservers(String tweet); 
} 

Subject使用registerObserver方法可以注册一个新的观察者,使用notifyObservers方法通知它的观察者一个新闻的到来。更进一步,实现Feed类:

class Feed implements Subject { private final List<Observer> observers = new ArrayList<>(); public void registerObserver(Observer o) { this.observers.add(o); } public void notifyObservers(String tweet) { observers.forEach(o -> o.notify(tweet)); } 
}

这是一个非常直观的实现:Feed类在内部维护了一个观察者列表,一条新闻到达时,它就进行通知。

	Feed f = new Feed(); f.registerObserver(new NYTimes()); f.registerObserver(new Guardian()); f.registerObserver(new LeMonde()); f.notifyObservers("The queen said her favourite book is Java 8 in Action!"); 

上面示例中,《卫报》会特别关注这条新闻。
使用Lambda表达式
Observer接口的所有实现类都提供了一个方法:notify。新闻到达时,它们都只是对同一段代码封装执行。Lambda表达式的设计初衷就是要消除这样的僵化代码。使用Lambda表达式后,无需显式地实例化三个观察者对象,直接传递Lambda表达式表示需要执行的行为即可:

f.registerObserver((String tweet) -> { if(tweet != null && tweet.contains("money")) { System.out.println("Breaking news in NY! " + tweet); } 
}); f.registerObserver((String tweet) -> { if(tweet != null && tweet.contains("queen")) { System.out.println("Yet another news in London... " + tweet); } 
}); 

是否随时随地都可以使用Lambda表达式呢?答案是否定的!前文介绍的例子中,Lambda适配得很好,那是因为需要执行的动作都很简单,因此才能很方便地消除僵化代码。但是,观察者的逻辑有可能十分复杂,它们可能还持有状态,抑或定义了多个方法,诸如此类。在这些情形下,还是应该继续使用类的方式。

责任链模式

责任链模式是一种创建处理对象序列(比如操作序列)的通用方案。一个处理对象可能需要在完成一些工作之后,将结果传递给另一个对象,这个对象接着做一些工作,再转交给下一个处理对象,以此类推。

通常,这种模式是通过定义一个代表处理对象的抽象类来实现的,在抽象类中会定义一个字段来记录后续对象。一旦对象完成它的工作,处理对象就会将它的工作转交给它的后继。代码中,这段逻辑看起来是下面这样:

public abstract class ProcessingObject<T> { protected ProcessingObject<T> successor; public void setSuccessor(ProcessingObject<T> successor) { this.successor = successor;} public T handle(T input) { T r = handleWork(input); if(successor != null) { return successor.handle(r); } return r; } abstract protected T handleWork(T input); 
} 

下图以UML的方式阐释了责任链模式。
在这里插入图片描述
handle方法提供了如何进行工作处理的框架。不同的处理对象可以通过继承ProcessingObject类,提供handleWork方法来进行创建。

下面看看如何使用该设计模式。可以创建两个处理对象,它们的功能是进行一些文本处理工作。

public class HeaderTextProcessing extends ProcessingObject<String> { public String handleWork(String text) { return "From Raoul, Mario and Alan: " + text; } 
} public class SpellCheckerProcessing extends ProcessingObject<String> { public String handleWork(String text) { return text.replaceAll("labda", "lambda"); } 
} 

现在你就可以将这两个处理对象结合起来,构造一个操作序列:

	ProcessingObject<String> p1 = new HeaderTextProcessing(); ProcessingObject<String> p2 = new SpellCheckerProcessing(); p1.setSuccessor(p2);//将两个处理对象链接起来String result = p1.handle("Aren't labdas really sexy?!!"); System.out.println(result); //打印输出“From Raoul, Mario and Alan: Aren't lambdas really sexy?!!

使用Lambda表达式
可以将处理对象作为函数的一个实例,为了链接这些函数,需要使用andThen方法对其进行构造。

	UnaryOperator<String> headerProcessing = (String text) -> "From Raoul, Mario and Alan: " + text; //第一个处理对象UnaryOperator<String> spellCheckerProcessing = (String text) -> text.replaceAll("labda", "lambda");  //第二个处理对象Function<String, String> pipeline = headerProcessing.andThen(spellCheckerProcessing); //将两个方法结合起来,结果就是一个操作链String result = pipeline.apply("Aren't labdas really sexy?!!");

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

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

相关文章

积分商城运营成功的7个关键要素

积分商城是一种受欢迎的私域营销工具&#xff0c;可以帮助企业吸引和留住客户&#xff0c;提高销售和客户忠诚度。然而&#xff0c;要确保积分商城的运营成功&#xff0c;需要考虑多个关键要素。本文将深入探讨这些要素&#xff0c;以帮助企业打造一个成功的积分商城。 第一要…

VIO和预积分(蒙圈的请过来,带你不蒙圈)

大佬的世界&#xff0c;你不会懂&#xff0c;就像一行行公式&#xff0c;人家觉得很简单&#xff0c;你却要读很多遍&#xff0c;不过还好&#xff0c;我们从普通人的世界来解读VIO和预积分。 预积分 拿大佬的话来热场&#xff0c;本章要介绍一种在紧耦合系统中十分常见的IMU…

IOTDB的TsFile底层设计

目录 概述 数据模型 数据结构 元数据注册 读取和写入 设计思想 主要过程

it网络设备监控系统

企业对网络监控系统的需求也在增加。网络监控系统是一种软件和硬件的组合&#xff0c;用于监控和管理企业的网络系统。它帮助企业实时了解网络情况&#xff0c;防范和处理网络问题&#xff0c;保证企业业务的正常使用。那么&#xff0c;IT网络监控系统监控什么设备呢&#xff1…

前端求职指南

简历求职指南 为什么没有面试&#xff1f; 1、简历写的不好 2、简历投递不好 简历的定义是什么&#xff1f; 是求职者向未来雇主展示自己专业技能和职业素养的自我推销工具&#xff0c;以找到工作为目的。 什么时候改简历&#xff1f; 每半年或一年更新一次工作中的成长 再工…

基于VR元宇宙技术搭建林业生态模拟仿真教学系统

随着科技的飞速发展&#xff0c;教学方式也正在经历着巨大的变革。林业经济学元宇宙虚拟教学系统作为一种新兴的教学方式&#xff0c;为学生和教师提供了一个全新的、沉浸式的学习和教学环境。 森林管理和监测 元宇宙技术可以用于森林管理和监测。通过无人机、传感器和虚拟现实…

docker 安装 nessus新版、awvs15-简单更快捷

一、docker 安装 nessus 参考项目地址&#xff1a; https://github.com/elliot-bia/nessus 介绍&#xff1a;几行代码即可一键安装更新 nessus -推荐 安装好 docker后执行以下命令 #拉取镜像创建容器 docker run -itd --nameramisec_nessus -p 8834:8834 ramisec/nessus …

GoogleTest部署实践--测试用例代码

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、GoogleTest简介二、GoogleTest工具适用岗位--测开岗、开发岗三、GoogleTest的理念四、GoogleTest的环境搭建五、GoogleTest 实战--编写googlet…

Spring Boot自动装配原理超详细解析

目录 前言一、什么是SPI&#xff1f;1. JDK中的SPI2. Spring中的SPI2.1 加载配置2.2 实例化 二、Import注解和ImportSelector是什么&#xff1f;1. 代码示例2. 过程解析3. 源码分析 三、Spring Boot的自动装配1.源码分析2.代码示例3.Spring Boot自带的自动装配 四、总结 前言 …

算法基础之二分查找

原题链接 一 、二分查找中的mid1和mid-1的问题 二分查找中的边界问题处理不好很容易导致死循环和计算错误的问题&#xff0c;以题目 数的范围为例。 题目大意 ​ 二分查找重复数第一次出现的位置和最后一次出现的位置。 数学含义 ​ 第一次位置即 找到 一个长度最大的 >X 区…

golang入门笔记——pprof性能分析

文章目录 简介runtime/pprof的使用命令行交互网络服务性能分析pprof与性能测试结合压测工具go-wrk 简介 golang性能分析工具pprof的8个指标 1.性能分析的5个方面&#xff1a;CPU、内存、I/O、goroutine&#xff08;协程使用情况和泄漏检查&#xff09;、死锁检测以及数据竟态…

医院电子病历编辑器,EMRE(EMR Editor)源码

电子病历主要面向医院机构医生、护士&#xff0c;提供对住院病人的电子病历书写、保存、修改、打印等功能。本系统基于云端SaaS服务方式&#xff0c;通过浏览器方式访问和使用系统功能&#xff0c;提供电子病历在线制作、管理和使用的一体化电子病历解决方案&#xff0c;为医疗…

asisctf 2023 web hello wp

hello 开题&#xff0c;直接给了源码。 <?php /* Read /next.txt Hint for beginners: read curls manpage. */ highlight_file(__FILE__); $url file:///hi.txt; if(array_key_exists(x, $_GET) &&!str_contains(strtolower($_GET[x]),file) && !str_c…

pandas argmax 和max区别

argmax 和 max 是 Pandas 中的两个函数&#xff0c;它们在处理数据时发挥了不同的作用。 argmax函数用于返回数据集中最大&#xff08;或最小&#xff09;值的索引。如果数据集中有多个相同的最大&#xff08;或最小&#xff09;值&#xff0c;那么这个函数将返回第一个出现该…

TVP专家谈腾讯云 Cloud Studio:开启云端开发新篇章

导语 | 近日&#xff0c;由腾讯云 TVP 团队倾力打造的 TVP 吐槽大会第六期「腾讯云 Cloud Studio」专场圆满落幕&#xff0c;6 位资深的 TVP 专家深度体验腾讯云 Cloud Studio 产品&#xff0c;提出了直击痛点的意见与建议&#xff0c;同时也充分肯定了腾讯云 Cloud Studio 的实…

el-table 指定层级展开

先来看看页面默认全部展开时页面的显示效果&#xff1a;所有节点被展开&#xff0c;一眼望去杂乱无章&#xff01; 那么如何实现只展开指定的节点呢&#xff1f;最终效果如下&#xff1a;一眼看去很舒爽。 干货上代码&#xff1a; <el-table border v-if"refreshTabl…

ROS2 从头开始:第 5 部分 - 并发、执行器和回调组

一、说明 让我们回到基础。并发意味着系统或软件可以同时运行许多任务。例如,在单核 CPU 机器上,可以通过使用线程来实现并发。本文探讨了

基于边缘智能网关的储充一体电站管理方案

在“2030碳达峰&#xff0c;2060碳中和”的目标下&#xff0c;我国持续加快推进能源转型&#xff0c;扩大新能源占比&#xff0c;全国各地都在部署建设光伏、储能、新能源汽车充电等应用。随着新能源汽车的广泛普及&#xff0c;充电站、充电桩的需求快速增加&#xff0c;行业也…

分享从零开始学习网络设备配置--任务3.8 使用动态路由OSPF实现网络连通

任务描述 某公司随着规模的不断扩大&#xff0c;路由器的数量在原有的基础上有所增加。网络管理员发现原有的路由协议已经不适合现有的网络环境&#xff0c;可实施动态路由OSPF协议配置&#xff0c;实现网络中所有主机之间互相通信。因为动态路由OSPF协议可以实现快速收敛&…

zabbix实现钉钉报警

首先钉钉创建一个团队 自定义关键词 查看zabbix-server脚本存放的位置&#xff1a; [rootcontrolnode ~]# grep ^AlertScriptsPath /etc/zabbix/zabbix_server.conf AlertScriptsPath/usr/lib/zabbix/alertscripts zabbix server设置 在配置文件书写脚本目录vim /etc/za…