2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

用现代 Java 调整经典设计模式

  • 2022-10-28
    北京
  • 本文字数:2955 字

    阅读完需:约 10 分钟

用现代Java调整经典设计模式

1998 年出版的《设计模式——可复用面向对象软件的基础》有资格成为计算机科学的经典著作,大学仍然将它作为教材,并被奉为业界的最佳实践。在 Devoxx 的一场深度讨论中,Venkat Subramaniam使用现代 Java 实现了迭代器策略装饰器工厂方法模式,对原有的设计模式进行了一番调整。


讨论的引言部分,Subramaniam 表示这本书的作者是软件开发的祖父,他们的设计模式是祖母的食谱——但即使你有了这些食谱,也不一定能做出这些菜。因此,他认为将设计模式作为一种沟通工具是有意义的,但将其作为一种软件设计工具却是一场灾难。


以下是我们在日常编程中可能遇到的常见模式,Subramaniam 通过充满活力和快乐的方式让这些模式变得更加流式。


由于 Java 加入了函数式编程,迭代器模式发生了很大的变化。最大的一个变化是从外部迭代器到内部迭代器的转变,这是 Java 函数式 API 带来的。这个变化可以让你从使用冗长的命令式迭代


int count = 0;for(var name: names) {   if(name.length() == 4) {     System.out.println(name.toUpperCase());   count++;
if(count == 2) { break; } } }}
复制代码


演变成使用流式的函数式迭代


names.stream()     .filter(name -> name.length() == 4)     .map(String::toUpperCase)     .limit(2)     .forEach(System.out::println);
复制代码


limit(long)takeWhile(Predicate<? super T>)(在 Java 9 中添加的)是continuebreak语句的等效函数,第一个只接受数值限制参数,而第二个可以接受表达式。


尽管 Java 的函数式 API 作为 JDK 的一部分已经有近十年的时间了,但在代码库中仍然存在一些常见的错误。当函数管道“不”纯粹(修改或依赖外部可见的状态)时,可能会导致迭代操作的结果不可预测(特别是在进行并行执行时)。


策略模式——我们希望改变算法的一小部分,同时保持算法的其余部分不变。从历史上看,这个模式是通过一个方法来实现的,这个方法采用一个方法接口作为参数,作为参数的方法接口可以有多个策略实现,一个策略通常就是一个方法或函数。因此,函数式接口和 lambda 表达式在这里很适用。


虽然匿名类可以作为一种实现机制,但函数接口(Predicate<? super T>是一个很好的选择)或 lambda 表达式让代码变得更加流式,更容易理解。在现代 Java 中,策略模式更多的是一种特性,而不是需要付出大量努力才能实现的模式。


public class Sample {  public static int totalValues(List<Integer> numbers) {    int total = 0;
for(var number: numbers) { total += number; }
return total; }
public static int totalEvenValues(List<Integer> numbers) { int total = 0;
for(var number: numbers) { if(number % 2 == 0) { total += number; } }
return total; }
public static int totalOddValues(List<Integer> numbers) { int total = 0;
for(var number: numbers) { if(number % 2 != 0) { total += number; } }
return total; }
public static void main(String[] args) { var numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println(totalValues(numbers)); System.out.println(totalEvenValues(numbers)); System.out.println(totalOddValues(numbers)); }}
复制代码


现代的做法是使用 lambda 表达式来表示策略。


import java.util.function.Predicate;
public class Sample { public static int totalValues(List<Integer> numbers, Predicate<Integer> selector) { int total = 0;
for(var number: numbers) { if(selector.test(number)) { total += number; } }
return total; }
public static boolean isOdd(int number) { return number % 2 != 0; }
public static void main(String[] args) { var numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println(totalValues(numbers, ignore -> true)); System.out.println(totalValues(numbers, number -> number % 2 == 0));
System.out.println(totalValues(numbers, Sample::isOdd)); }}
复制代码


在介绍工厂方法实现时,Venkat 陈述了以下内容。


从多态的角度来看,Java 中最糟糕的关键字是什么?尽管 final、instanceof 和 static 都可能算是最糟糕的关键字,但它们都只是小兵,new才是它们当中的黑手党。多模式(创建模式)、框架(SpringGuice)是为了解决 new 的“弊端”——缺乏多态性支持和紧密耦合。受Ruby基于上下文创建不同对象的多态能力的启发,Venkat 使用 Java 的default关键字实现工厂方法模式。这种方法使用了接口和非常小的实现类,让代码变得更容易理解。


import java.util.*;
interface Pet {}class Dog implements Pet {}class Cat implements Pet {}
interface Person { Pet getPet();
default void play() { System.out.println("playing with " + getPet()); }}
class DogPerson implements Person { private Dog dog = new Dog();
public Pet getPet() { return dog; }}
class CatLover implements Person { private Cat cat = new Cat(); public Pet getPet() { return cat; }}
public class Sample { public static void call(Person person) { person.play(); }
public static void main(String[] args) { call(new DogPerson()); call(new CatLover()); }}
复制代码


即使装饰器模式在理论上为许多程序员所熟知,但实际上很少有人使用它。它的实现最臭名昭著的例子可能是 io 包。Venkat 基于函数的可组合性提出了一种不同的方法——使用identity函数和andThen(Function<? super R,? extends V>)构建简单、流式的机制来增强对象的能力。


class Camera {  private Function<Color, Color> filter;
public Camera(Function<Color, Color>... filters) { filter = Stream.of(filters) .reduce(Function.identity(), Function::andThen); }
public Color snap(Color input) { return filter.apply(input); }}
public class Sample { public static void print(Camera camera) { System.out.println(camera.snap(new Color(125, 125, 125))); }
public static void main(String[] args) { print(new Camera());
print(new Camera(Color::brighter)); print(new Camera(Color::darker));
print(new Camera(Color::brighter, Color::darker)); }}
复制代码


即使模式看起来会一直存在,就像 Subramaniam在讨论中提到的:“设计模式经常被用来填补编程语言的空白。一门语言越强大,我们就越少谈论设计模式,因为设计模式自然会成为语言的特性。”


随着编程语言的演进和我们经验的积累,模式也会随着时间的推移而演变。其中一些模式被吸收为语言的特性,另一些则被认为已过时,而另一些变得更加容易实现。不管你最喜欢的是哪一类,Venkat 建议把它们作为交流的手段,并让代码朝着这些模式的方向演变。此外,他建议尝试使用多种编程语言,让代码变得更加流式。


原文链接

https://www.infoq.com/news/2022/10/modern-java-design-patterns/

2022-10-28 09:559305

评论

发布
暂无评论
发现更多内容

CMMI V2.0丨如何通过CMMI真正在企业中的实施规模化敏捷开发

IPD产品研发管理

软件 研发管理 CMMI

中公、马士兵、千锋、拉勾入局,腾讯课堂“薪选”IT人才培养按下加速键

DT极客

“为爱而生 温暖陪伴”——2021年中国洗地机行业发展峰会圆满落幕

DT极客

多方安全计算:隐私保护集合求交技术

华为云开发者联盟

数据集 PSI 隐私保护集合交集 可信 伪随机函数

国内日志监控分析王者之sls

代码先生

分布式日志 海量数据分析 日志监控分析

Windows Terminal 安装和运行

HoneyMoose

关于OpenHarmony 2.0共建进展

罗燕珊

开源 鸿蒙 OpenHarmony

不给电脑,我用手机敲命令十分钟完成了zabbix监控,面试官当场下offer

沐风

监控 zabbix

uniapp 使用原生子窗体进行视频聊天

anyRTC开发者

uni-app 音视频 WebRTC RTC

亿级系统的Redis缓存如何设计?

Java架构师迁哥

拍乐云将亮相 QCon 大会,揭秘音视频“两高一低”体验背后的技术

拍乐云Pano

Windows 任务管理器中如何显示 CPU 逻辑处理器情况

HoneyMoose

快成物流科技 x mPaaS | 小程序容器加持下的技术架构“提质增效”

蚂蚁集团移动开发平台 mPaaS

小程序 移动开发 mPaaS

RDBMS与HBase的对比

五分钟学大数据

大数据 HBase 5月日更

Hadoop定位问题日志跟踪

InfoQ_Springup

hadoop

This BigData,Hadoop组成及生态

Simon郎

大数据 hdfs YARN hadoop3

GitHub开源史上最大规模中文知识图谱

不脱发的程序猿

人工智能 自然语言处理 GitHub 开源 中文知识图谱

🚄【Redis 干货领域】帮你完全搞定Sentinel运作原理

码界西柚

redis哨兵模式 redis哨兵 redis哨兵集群 redis sentinel 5月日更

墨奇科技宣布完成 2.5 亿元 B 轮融资

E科讯

GitHub收藏最高的10个Java练手项目推荐

北游学Java

Java spring 项目实战

2021高级Android笔试总结,Android系列学习进阶视频

欢喜学安卓

android 程序员 面试 移动开发

Pulumi 如何在 Windows 环境中设置

HoneyMoose

一张图看懂嵌入式系统组成

不脱发的程序猿

硬件开发 嵌入式系统 嵌入式学习路线

云小课|DSC帮您管数据,保障您的云上数据安全

华为云开发者联盟

数据安全 华为云 数据安全中心 云上数据 DSC

CODING CD + Nginx Ingress 实现蓝绿发布

CODING DevOps

DevOps 敏捷开发 研发管理 CODING 研发团队

微软 WSL 重装操作系统

HoneyMoose

【LeetCode】将句子排序Java题解

Albert

算法 LeetCode 5月日更

Too many open files 的四种解决办法

ilinux

并行文件存储和分布式 NFS 文件存储有何不同

焱融科技

容器 云原生 高性能 文件存储 技术博客

5G进京 “赶考”记:“占得上、保持稳、体验优、信号好”四道考题,分别打几分?

脑极体

融云2021 X-Meetup技术沙龙 探讨音视频技术新方向

融云 RongCloud

用现代Java调整经典设计模式_语言 & 开发_Olimpiu Pop_InfoQ精选文章