Lambda 重构面向对象的设计模式
Lambda 重构面向对象的设计模式
策略模式
策略模式包含三部分内容
一个代表某个算法的接口(它是策略模式的接口)。
一个或多个该接口的具体实现,它们代表了算法的多种实现(比如,实体类ConcreteStrategyA或者ConcreteStrategyB)。
一个或多个使用策略对象的客户
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");
Validator lowerCaseValidator = new Validator(new IsAllLowerCase ());
boolean b2 = lowerCaseValidator.validate("bbbb");
Validator numericValidator = new Validator((String s) -> s.matches("[a-z]+"));
boolean b1 = numericValidator.validate("aaaa");
Validator lowerCaseValidator = new Validator((String s) -> s.matches("\\d+"));
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);
}
使用Lambda表达式
public void processCustomer(int id, Consumer<Customer> makeCustomerHappy){ Customer c = Database.getCustomerWithId(id); makeCustomerHappy.accept(c);
} new OnlineBankingLambda().processCustomer(1337, (Customer c) -> System.out.println("Hello " + c.getName());
观察者模式
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); } }
} interface Subject{ void registerObserver(Observer o); void notifyObservers(String tweet);
} 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 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表达式
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);
} 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);
使用Lambda表达式
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?!!")
工厂模式
public class ProductFactory { public static Product createProduct(String name){ switch(name){ case "loan": return new Loan(); case "stock": return new Stock(); case "bond": return new Bond(); default: throw new RuntimeException("No such product " + name); } }
}
Product p = ProductFactory.createProduct("loan");
使用Lambda表达式
final static Map<String, Supplier<Product>> map = new HashMap<>();
static { map.put("loan", Loan::new); map.put("stock", Stock::new); map.put("bond", Bond::new);
} public static Product createProduct(String name){ Supplier<Product> p = map.get(name); if(p != null) return p.get(); throw new IllegalArgumentException("No such product " + name);
}
相关文章:
Lambda 重构面向对象的设计模式
Lambda 重构面向对象的设计模式 策略模式 策略模式包含三部分内容 一个代表某个算法的接口(它是策略模式的接口)。 一个或多个该接口的具体实现,它们代表了算法的多种实现(比如,实体类ConcreteStrategyA或者Concrete…...
element ui 上传组件实现手动上传
首先需要给上传组件增加http-request属性,这个方法中可以获取到文件,并按照自己的方式进行上传。 <el-uploadreffileUploadaction#:http-requesthttpRequest:on-preview"handlePreview":on-remove"handleRemove":limit"1&q…...
怎样提升伦敦银买卖技巧?
如果投资者想提升伦敦银的买卖技巧,可以学习一些有用的技术分析方法。所谓技术分析,就是通过对行情过往价格和相关交易数据进行收集,用图表的方式解读白银市场,进而预测行情未来主线走势、判断价格细节变化、寻找重要支撑点阻力点…...
MySQL的体系结构与SQL的执行流程
文章目录 前言体系结构SQL语句的执行流程1、连接MySQL2、查询缓存3、解析SQL语句4、优化SQL语句5、执行SQL语句 总结 前言 如果你在使用MySQL时只会写sql语句的,那么你应该看一下《MySQL优化的底层逻辑》。如果你只了解到sql是如何优化的,那么你应该通过…...
数学建模之拟合及其代码
发现新天地,欢迎访问Cr不是铬的个人网站 引言 与插值问题不同,在拟合问题中不需要曲线一定经过给定的点。拟合问题的目标是寻求一个函数(曲线),使得该曲线在某种准则下与所有的数据点最为接近,即曲线拟合…...
GeoTrust SSL数字安全证书介绍
一、GeoTrust OV证书的介绍 GeoTrust OV证书是由GeoTrust公司提供的SSL证书,它是一种支持OpenSSL的数字证书,具有更高的安全性和可信度。GeoTrust是全球领先的网络安全解决方案提供商,为各类用户提供SSL证书和信任管理服务。GeoTrust OV证书…...
【C++上层应用】5. 文件和流
文章目录 【 1. 打开文件 】1.1 open 函数1.2 open 多种模式的结合使用 【 2. 关闭文件 】【 3. 写入 & 读取文件 】【 4. 文件位置指针 】 和 iostream 库中的 cin 标准输入流和 cout 标准输出流类似,C中另一个库 fstream 也存在文件的读取流和标准写入流。fst…...
JAVA爬虫1 - HttpClient的使用
一、简介 HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的 项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit…...
NX二次开发UF_CSYS_map_point 函数介绍
文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_CSYS_map_point Defined in: uf_csys.h int UF_CSYS_map_point(int input_csys, double input_point [ 3 ] , int output_csys, double output_point [ 3 ] ) overview 概述 Ma…...
Spring Web MVC
目录 一.简介 二.建立连接(客户端和服务器) 三.请求 1.传递单个参数 2.传递多个参数 3.对象 4.数组/集合 5.JSON 6.URL参数 7.上传文件 8.获取cookie和session (1)获取cookie (2)获取session …...
Debian系列的Linux发行版上部署wvp
Debian系列的Linux发行版上部署wvp 环境搭建1.Debian系列的Linux发行版上安装nginx2.安装mysql设置mysql密码修改权限sudo mysql ERROR 1045 (28000): Access denied for user root@localhost (using password: NO)配置相关navicat 连接不上 报错 10061navicat 连接报错 1130 -…...
无人智能柜:经营成本低,运维智能化
在现代商业领域中,无人智能柜正逐渐崭露头角,成为一种具有前景的商业模式。其独特之处在于经营成本的低廉性和运维过程的智能化。相较于传统的便利店等实体店铺,无人智能柜在运营过程中不仅能够降低成本,还能够实现高效的运维管理…...
java.lang.UnsupportedOperationException 关于Arrays.asList问题解决
解析String 字符串为List集合ArrayList<String> itemsList Arrays.asList(items.split("\\|")List<String> itemsList Arrays.asList(items.split("\\|")final Iterator<String> iterator itemsList.iterator();while (iterator.hasNex…...
2023.11.23 云服务器实现 Spring Boot 项目文件上传并访问
环境介绍 云服务器:京东云云服务器系统: CentOS 7.9JDK 版本:1.8Spring Boot 版本:2.7.17 具体步骤 步骤一 首先我们得先创建一个 Spring Boot 项目 创建如下目录结构 关于如何创建一个 Spring Boot 项目 请点击下方链接详细了解 …...
SAP实现多个统御科目:特殊总账SGL+备选统驭科目Alternative Reconciliation Accounts
以前只知道特别总账。学习了 客商的每个公司视图主数据唯一分配一个统驭科目。一般情况下,客商经常发生的业务对应的总帐科目设为统驭科目。 客户设置的统驭科目:应收账款 供应商设置的统驭科目:应付账款 除了经常的销售和采购业务对应应收和…...
【数据分享】2023年我国省市县三级的瞪羚企业数量(免费获取/Excel/Shp格式)
企业是经济活动的参与主体。一个城市的企业数量决定了这个城市的经济发展水平!比如一个城市的金融企业较多,那这个城市的金融产业肯定比较发达;一个城市的制造业企业较多,那这个城市的制造业肯定比较发达。 之前我们给大家分享了…...
用于计算机屏幕安全摄像头系统:Screen Anytime Crack
Screen Anytime 是一款软件,旨在自动将整个用户会话或 PC/服务器/VM/Kiosk 的 /RDP/Citrix/RemoteApp 会话的屏幕活动记录到视频日志文件中,以用于记录、审核和监控目的。通过重播其高度压缩的视频,您可以轻松回顾单台计算机或一组服务器/PC …...
Redis深入理解-Socket连接建立流程以及文件事件处理机制
Redis Server 运行原理图 Redis 服务器中 Socket 网络建立以及文件事件模型 一个 redis 单机,可以抗几百上千的并发,这里的并发指的就是同时可以有几百个 client 对这个 redis server 发起请求,都需要去建立网络连接,同时间可能会…...
Docker run 命令
docker run :创建一个新的容器并运行一个命令 语法 docker run [OPTIONS] IMAGE [COMMAND] [ARG...]OPTIONS说明: -a stdin:指定标准输入输出内容类型,可选STDIN/STDOUT/STDERR三项; -d:后台运行容器&am…...
Vue中的$nextTick的作用
在 Vue 中,当某些数据发生变化时,DOM 并不会立即更新。相反,Vue 会在下一个事件循环周期(microtask)中异步执行更新,这样可以避免频繁的 DOM 操作。然而,有时候我们需要在 DOM 更新后执行一些操…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
