函数式编程让你忘记设计模式

本文是一篇《Java 8实战》的阅读笔记,阅读大约需要5分钟。

有点标题党,但是这确实是我最近使用Lambda表达式的感受。设计模式是过去的一些好的经验和套路的总结,但是好的语言特性可以让开发者不去考虑这些设计模式。面向对象常见的设计模式有策略模式、模板方法、观察者模式、责任链模式以及工厂模式,使用Lambda表达式(函数式编程思维)有助于避免面向对象开发中的那些固定代码。下面我们挑选了策略模式和职责链模式两个案例进行分析。

案例1:策略模式

721786-20190707222328197-2036783858.jpg

当我们解决一个问题有不同的解法的时候,又不希望客户感知到这些解法的细节,这种情况下适合使用策略模式。策略模式包括三个部分:

  • 解决问题的算法(上图中的Strategy);
  • 一个或多个该类算法的具体实现(上图中的ConcreteStrategyA、ConcreteStrategyB和ConcreteStrategyC)
  • 一个或多个客户使用场景(上图中的ClientContext)

面向对象思路

首先定义策略接口,表示排序策略:

public interface ValidationStrategy {boolean execute(String s);
}

然后定义具体的实现类(即不同的排序算法):

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

最后定义客户使用场景,代码如下图所示。Validator是为客户提供服务时使用的上下文环境,每个Valiator对象中都封装了具体的Strategy对象,在实际工作中,我们可以通过更换具体的Strategy对象来进行客户服务的升级,而且不需要让客户进行升级。

public class Validator {private final ValidationStrategy strategy;public Validator(ValidationStrategy strategy) {this.strategy = strategy;}/*** 给客户的接口*/public boolean validate(String s) {return strategy.execute(s);}
}public class ClientTestDrive {public static void main(String[] args) {Validator numbericValidator = new Validator(new IsNumberic());boolean res1 = numbericValidator.validate("7780");System.out.println(res1);Validator lowerCaseValidator = new Validator(new IsAllLowerCase());boolean res2 = lowerCaseValidator.validate("aaaddd");System.out.println(res2);}
}

函数式编程思路

如果使用Lambda表达式考虑,你会发现ValidationStrategy就是一个函数接口(还与Predicate具有同样的函数描述),那么就不需要定义上面那些实现类了,可以直接用下面的代码替换,原因是Lambda表达式内部已经对这些类进行了一定的封装。

public class ClientTestDrive {public static void main(String[] args) {Validator numbericValidator = new Validator((String s) -> s.matches("\\d+"));boolean res1 = numbericValidator.validate("7789");System.out.println(res1);Validator lowerCaseValidator = new Validator((String s) -> s.matches("[a-z]+"));boolean res2 = lowerCaseValidator.validate("aaaddd");System.out.println(res2);}
}

案例2:责任链模式

在某些场景下,需要对一个对象做一系列的工作,这些工作分别是由不同的类完成的,这时候就比较适合使用责任链模式。责任链模式的主要组成部分包括三个:

  • 管理操作序列的抽象类,在该抽象类里有会有一个对象记录当前对象的后继操作对象;
  • 一些具体的操作对象,这些操作对象会以一个链表的形式组织起来
  • 一个使用该模式的客户端组件,该组件只需要跟一个组件打交道就好,不需要跟很多个操作对象耦合在一起。

721786-20190707222346886-1648676572.jpg

面向对象思路

首先看下我们这里定义了一个抽象类ProcessingObject,其中successor字段用于管理该对象的后继操作对象;handle接口作为对外提供服务的接口;handleWork作为实际处理对象的操作方法。

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

接下来可以定义两个具体的操作对象,如下面代码所示。PS:这里《Java 8实战》书中用的是replaceAll方法是不太合适的,这个点可以参考我们之前的文章——020:举几个String的API以及案例。

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

最后,你就可以在Client中将这上面两个具体的操作类对象构成一个操作序列,参见下面的代码:

public class Client {public static void main(String[] args) {ProcessingObject<String> p1 = new HeaderTextProcessing();ProcessingObject<String> p2 = new SpellCheckerProcessing();p1.setSuccessor(p2);String result = p1.handler("Aren't labdas really sexy?!!");System.out.println(result);}
}

函数式编程思路

如果使用函数式编程思维,那么职责链模式就直接了——y=f(x)和z=g(x)这两个方法都是要对x做处理,那么如果将这两个函数组合在一起,就会形成r=f(g(x))的情况,也就是可以使用Lambda表达式中的addThen来串联起多个处理过程。

public class ClientWithLambda {public static void main(String[] args) {UnaryOperator<String> headerProcessing = (String text) -> "From Raoul, Mario and Alan: " + text;UnaryOperator<String> spellCheckProcessing = (String text) -> text.replace("labda", "lambda");Function<String, String> function = headerProcessing.andThen(spellCheckProcessing);String result = function.apply("Aren't labdas really sexy?!!");System.out.println(result);UnaryOperator<String> hhhhhProcessing = (String text) -> text.concat("hhhh");Function<String, String> function1 = function.andThen(hhhhhProcessing);String result1 = function1.apply("Aren't labdas really sexy?!!");System.out.println(result1);}
}

上面是利用Java原生的Lambda表达式实现的职责链模式,我们也可以使用前面一篇文章——vavr:让你像写Scala一样写Java中介绍过的vavr库来实现,代码如下所示:

public class ClientWithVavr {public static void main(String[] args) {Function1<String, String> headerProcessing = (String text) -> "From Raoul, Mario and Alan: " + text;Function1<String, String> specllCheckProcessing = (String text) -> text.replace("labda", "lambda");Function1<String, String> function = headerProcessing.compose(specllCheckProcessing);String result = function.apply("Aren't labdas really sexy?!!");System.out.println(result);}
}

总结

可以看出,函数式编程思维跟面向对象编程思维的思考方式是不同的,表达力更强,因此,作为开发者是时候认真学习下函数式编程思维了,作为Java开发者,我准备先从Lambda表达式开始学起,然后尝试学习下Scala或Kotlin两门语言中的函数式编程特性。

参考资料

  1. 《Java编程实战》
  2. 《设计模式之禅》

本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。javaadu

转载于:https://www.cnblogs.com/javaadu/p/11148006.html

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

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

相关文章

25年,100亿美元!人类「第二只眼」韦伯望远镜升空,寻找宇宙开天辟地那束光...

来源&#xff1a;新智元编辑&#xff1a;桃子 小咸鱼昨晚&#xff0c;历时25年研发&#xff0c;100亿美金打造的詹姆斯韦伯太空望远镜终于升空&#xff01;它将成为人类的「第二只眼」&#xff0c;奔向离地球150万公里外的地方&#xff0c;不仅为了仰望星空&#xff0c;更是为了…

计算机网络学习笔记-1.2.2OSI参考模型(1)

计算机网络-2019 王道考研 计算机网络-1.2.2OSI参考模型&#xff08;1&#xff09; 文章目录2.OSI参考模型&#xff08;1&#xff09;2.1OSI参考模型&#xff08;1&#xff09;2.2ISO/OSI参考模型2.3ISO/OSI参考模型解释通信过程2.OSI参考模型&#xff08;1&#xff09; 2.1OS…

计算机网络学习笔记-1.2.3OSI参考模型(2)

计算机网络-[2019 王道考研 计算机网络-1.2.3OSI参考模型&#xff08;2&#xff09;(https://www.bilibili.com/video/av70228743?t6&p7) 文章目录3.OSI参考模型&#xff08;2&#xff09;3.1应用层3.2表示层3.3会话层3.4传输层3.5网络层3.6数据链路层3.7物理层3.8思维导图…

科技城|从专利布局看人工智能领域全球竞争与中国面临的挑战

来源&#xff1a;澎湃新闻作者&#xff1a;杜灵君&#xff08;来自中国电子信息产业发展研究院&#xff09;近年来&#xff0c;随着人工智能技术的突破&#xff0c;人工智能产业爆发式增长。全球各个国家为了抢占产业发展和技术变革主导权&#xff0c;争相出台政策、资本、核心…

计算机网络学习笔记-1.2.4TCP,IP参考模型和五层参考模型

计算机网络-2019 王道考研 计算机网络-1.2.4TCP&#xff0c;IP参考模型和五层参考模型 文章目录4.TCP&#xff0c;IP参考模型和五层参考模型4.1OSI参考模型与TCP/IP参考模型4.2OSI参考模型与TCP/IP参考模型的相同点4.3OSI参考模型与TCP/IP参考模型的不同点4.4五层参考协议4.4五…

从城市大脑到世界数字大脑 构建人类协同发展的超级智能平台

作者&#xff1a;远望智库数字大脑研究院院长&#xff0c;中国科学院虚拟经济与数据科学研究中心研究组成员&#xff0c;南京财经大学教授 刘锋&#xff08;本文2021年12月发表于中国建设信息化&#xff09;一&#xff0e;世界数字大脑产生的背景世界数字大脑与城市大脑的产生…

计算机网络学习笔记-1.2.3第一章总结

计算机网络-2019 王道考研 计算机网络-1.3第一章总结 文章目录3第一章总结3第一章总结

Science长文综述:通过空间斑图形成避免复杂系统崩溃

来源&#xff1a; 集智俱乐部作者&#xff1a;Max Rietkerk et al.译者&#xff1a;吕丽莎、胡一冰、李明章、郭瑞东、张澳审校&#xff1a;张澳、梁金编辑&#xff1a;邓一雪导语今天的地球处于人类世&#xff0c;人类活动对整个地球生态系统具有深刻影响。由于干旱和过度放牧…

计算机网络学习笔记-目录(更新日期:2020.4.8)

导语&#xff1a;文章合为时而著,歌诗合为事而作&#xff0c;我们学习&#xff0c;也自然需要知道我们为什么学这玩意儿~ 对于计算机网络这门课呢&#xff0c;大家如果是计算机专业的学生&#xff0c;那就是必上的一门科目啦&#xff0c;但是为什么要上呢&#xff1f;对于不同的…

达摩院发布:2022年十大科技趋势

来源&#xff1a;达摩院刚刚&#xff0c;阿里巴巴达摩院发布2022十大科技趋势&#xff0c;这是达摩院连续第四年发布前沿科技趋势预测。达摩院分析了近三年来的770万篇公开论文、8.5万份专利&#xff0c;覆盖159个领域&#xff0c;深度访谈近100位科学家&#xff0c;提出了2022…

Nature癌症“牵线木偶”理论:科学家找到了不易误伤健康细胞的“剪刀”

来源&#xff1a;生物通密歇根大学健康罗格尔癌症中心的研究人员证明&#xff0c;SWI/SNF复合物有助于获取癌基因可以结合的增强子&#xff0c;并驱动癌症中的下游基因表达。降解这个复合体的亚基会阻断癌基因。这一发现揭示了一种治疗由不同基因驱动的前列腺癌的新方法&#x…

JavaSE进阶学习笔记-目录汇总(待完成)

声明&#xff1a;此博客来自于黑马程序员学习笔记&#xff0c;并非商用&#xff0c;仅仅是为了博主个人日后学习复习用&#xff0c;如有冒犯&#xff0c;请联系qq208820388立即删除博文&#xff0c;最后&#xff0c;来跟我一起喊黑马牛逼黑马牛逼黑马牛逼 JavaSE进阶学习笔记-…

IEEE 发布年终总结,AI 奇迹不再是故事

来源&#xff1a;AI科技大本营&#xff08;ID:rgznai100&#xff09;编译&#xff1a;禾木木2021 年&#xff0c;人工智能奇迹不再只是故事&#xff01;人工智能正在迅速融入各行各业&#xff0c;IEEE Spectrum 总结了 2021 年 10 篇最受读者欢迎的 AI 文章&#xff0c;按时间排…

JavaWeb学习笔记-目录(待完成)

JavaWeb学习笔记-目录&#xff08;待完成&#xff09; 01-基础加强&#xff08;注解反射&#xff09; 02-mysql基础 03-mysql约束 04-mysql多表事务 05-jdbc 06-jdbc连接池JDBCTemplate 07-html 08-css 09-js基础 10-js高级 11-bootstrap 12-xml 13-toncat-servel…

我们正处于新科学革命的起点 | 学界热议AI for Science

来源&#xff1a;科学网编辑&#xff1a;宗华排版&#xff1a;李言作者&#xff1a;赵广立我们正处于新科学革命的起点▲ 北京大学、普林斯顿大学教授 鄂维南数百年来&#xff0c;以数据驱动的开普勒范式和以第一性原理驱动的牛顿范式是科学研究的两大基本范式。当下正在蓬勃兴…

01-object类,常用API

声明&#xff1a;此博客来自于黑马程序员学习笔记&#xff0c;并非商用&#xff0c;仅仅是为了博主个人日后学习复习用&#xff0c;如有冒犯&#xff0c;请联系qq208820388立即删除博文&#xff0c;最后&#xff0c;来跟我一起喊黑马牛逼黑马牛逼黑马牛逼 01【Object类、常用A…

新型人工突触可用于高度扩展的类脑计算

来源&#xff1a;科技日报作者&#xff1a;张梦然科技日报北京12月28日电 &#xff08;记者张梦然&#xff09;据最新一期美国化学会期刊《应用材料与界面》报道&#xff0c;新加坡科技与设计大学&#xff08;SUTD&#xff09;研究团队开发出一种基于二维&#xff08;2D&#x…

03-list,set,数据结构,Collections

声明&#xff1a;此博客来自于黑马程序员学习笔记&#xff0c;并非商用&#xff0c;仅仅是为了博主个人日后学习复习用&#xff0c;如有冒犯&#xff0c;请联系qq208820388立即删除博文&#xff0c;最后&#xff0c;来跟我一起喊黑马牛逼黑马牛逼黑马牛逼 【List、Set、数据结…

O'Reilly创始人谈Web 3.0:我们将再次经历1999年互联网泡沫时期

来源&#xff1a;巴比特资讯原文作者&#xff1a;OReilly创始人Tim O’Reilly最近有很多关于 Web3 的讨论&#xff0c;作为在17年前定义“Web 2.0”的人&#xff0c;我经常被要求发表关于Web3的评论。但我通常会避免去这样做&#xff0c;因为大多数对未来的预测都被证明是错误的…

Liunx之nginx代理

一、代理 正向代理 正向代理&#xff0c;也就是传说中的代理,他的工作原理就像一个跳板&#xff08;VPN&#xff09;&#xff0c;简单的说&#xff1a; 我是一个用户&#xff0c;我访问不了某网站&#xff0c;但是我能访问一个代理服务器&#xff0c;这个代理服务器呢&#xff…