在本博客中,我将说明如何使用Java 8 Lambda表达式以函数式编程方式实现命令模式 。 命令模式的目的是将请求封装为对象,从而为具有不同请求,队列或日志请求的客户端参数化,并支持相应的操作。 命令模式是一种编写通用代码的方法,该代码根据运行时决策对序列进行排序并执行方法。 此模式的参与者如下:

  • 命令 –声明用于执行操作的接口。
  • ConcreteCommand –定义Receiver对象和操作之间的绑定。
  • 客户端 –创建ConcreteCommand实例并设置其接收者。
  • 调用程序 –控制命令以执行请求。
  • 接收器 –执行实际工作。

这些参与者之间的关系如下图所示:

让我们看一下命令模式的具体示例,看看如何用lambda表达式转换它。 假设我们有一个文件系统实用工具,该工具具有要调用的操作,例如打开文件,写入文件和关闭文件。 可以将其实现为宏功能-即可以记录的一系列操作,然后作为单个操作在以后运行。 这将是我们的接收者。

public interface FileSystemReceiver {void openFile();void writeFile();void closeFile();
}

每个操作(例如openFilewritefile )都是命令。 我们可以创建一个通用的命令界面以适合这些不同的操作。 我们将此接口称为“动作”,因为它表示在我们的域中执行单个动作。 这是我们所有命令对象都实现的接口。

public interface Action {public void perform();
}

现在让我们为每个操作实现Action接口。 所有这些类需要做的就是在FileReceiver上调用一个方法并将此调用包装到我们的Action接口中。 让我们以它们包装的操作命名它们,并使用适当的类命名约定-因此,openFile方法对应于一个名为OpenFile的类。

public class OpenFile implements Action {private final FileReceiver fileReceiver;public OpenFile(FileReceiver fileReceiver) {this.fileReceiver = fileReceiver;}public void perform() {fileReceiver.openFile();}}

现在,让我们实现Macro类。 宏由一系列可以依次调用的动作组成,它将充当调用者。 此类可以记录动作并集体运行它们。 我们可以将动作序列存储在List中,然后迭代获取每个动作以执行。

public class Macro {private final List actions;public Macro() {actions = new ArrayList<>();}public void record(Action action) {actions.add(action);}public void run() {actions.forEach(Action::perform);}
}

在填充宏时,我们可以将已记录的每个命令的实例添加到Macro对象。 现在简单地运行宏将依次调用每个命令。 这是我们的客户代码。

Macro macro = new Macro();
macro.record(new OpenFile(fileReceiver));
macro.record(new WriteFile(fileReceiver));
macro.record(new CloseFile(fileReceiver));
macro.run();

如果到目前为止您一直与我在一起,您会想知道lambda表达式在所有这些方面都适合。 实际上,我们所有的命令类,例如OpenFile,WriteFile和CloseFile,实际上只是希望突破包装的lambda表达式。 它们只是作为类传递的某些行为。 使用lambda表达式,整个模式变得更加简单,因为我们可以完全取消这些类。 让我们看看Macro类(客户端)如何使用lambda表达式代替命令类。

Macro macro = new Macro();
macro.record(() -> fileReceiver.openFile());
macro.record(() -> fileReceiver.writeFile());
macro.record(() -> fileReceiver.closeFile());
macro.run();

可以通过意识到这些lambda表达式中的每一个都在执行单个方法调用这一事实来进一步改善。 因此,方法引用可以直接使用。

Macro macro = new Macro();
macro.record(fileReceiver::openFile);
macro.record(fileReceiver::writeFile);
macro.record(fileReceiver::closeFile);
macro.run();

命令模式很容易扩展,可以在接收器中添加新的操作方法以创建新的命令实现,而无需更改客户端代码。 JDK中的Runnable接口(java.lang.Runnable)是使用Command模式的流行接口。 在这个博客中,我试图用Java 8 lambda表达式来表达命令模式。 通过使用lambda表达式,您会看到,所需的样板文件少得多,从而导致代码更简洁。

这篇文章的灵感来自Richard Warburton的文章使用带lambda表达式的命令模式 。

翻译自: https://www.javacodegeeks.com/2015/09/java-8-lambda-expression-for-design-patterns-command-design-pattern.html

设计模式的Java 8 Lambda表达式–命令设计模式相关推荐

  1. 设计模式的Java 8 Lambda表达式-策略设计模式

    策略模式定义封装在通常称为Context的驱动程序类中的一系列算法,并使这些算法可互换. 它使算法易于互换,并提供了在特定时间选择适当算法的机制. 算法(策略)在运行时由客户端或上下文选择. 在与客户 ...

  2. 设计模式的Java 8 Lambda表达式–策略设计模式

    策略模式定义封装在通常称为Context的驱动程序类中的一系列算法,并使这些算法可互换. 它使算法易于互换,并提供了在特定时间选择适当算法的机制. 算法(策略)在运行时由客户端或上下文选择. 在与客户 ...

  3. 设计模式的Java 8 Lambda表达式–装饰器设计模式

    Decorator模式(也称为Wrapper )允许将行为静态或动态地添加到单个对象,而不会影响同一类中其他对象的行为. 可以将其视为子类的替代方法. 我们知道子类在编译时会增加行为,并且更改会影响原 ...

  4. java.io设计模式_Java IO文件过滤器对命令设计模式的使用

    一. 点睛 java io流里面使用到了很多的设计模式,最典型的就是装饰模式,还有命令模式.通过对文件过滤器功能的简单使用,可以一窥java io流对命令设计模式的典型使用.下面分两部分来讲,先举例说 ...

  5. 10个Java 8 Lambda表达式经典示例

    Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表 达式,它将允许我们将行为传到函数里.在J ...

  6. Java 8 Lambda表达式10个示例【存】

    PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...

  7. Java 8 Lambda 表达式详解

    版权声明:本文由吴仙杰创作整理,转载请注明出处:https://segmentfault.com/a/1190000009186509 1. 引言 在 Java 8 以前,若我们想要把某些功能传递给某 ...

  8. Java 8 Lambda表达式-接口实现

    Java 8 Lambda表达式在只有一个方法的接口实现代码编写中,可以起到简化作用: (argument list) -> body 具体看Runnable接口的例子 public class ...

  9. 这是一个有趣的问题,Java 8 Lambda 表达式被编译成了什么?

    在了解了Java 8 Lambda的一些基本概念和应用后, 我们会有这样的一个问题: Lambda表达式被编译成了什么? 这是一个有趣的问题,涉及到JDK的具体的实现.本文将介绍OpenJDK对Lam ...

最新文章

  1. Hadoop集群的NameNode的备份
  2. 647. Palindromic Substrings
  3. nssl1338-逃亡路径【最短路计数,bfs】
  4. jmeter对oracle压力测试
  5. Spring Boot @Async 简单实践
  6. Spring(15)——基于注解的配置(二)
  7. python缓存技术_高级Python技术:如何在Python应用程序中实现缓存
  8. html隐藏safari地址栏,怎么隐藏 iOS Safari 打开网页时的地址栏和工具栏探索
  9. STM32驱动步进电机
  10. Prolog:list处理(复习笔记)
  11. chrome浏览器的devtools详解
  12. python中数组常用的统计方法
  13. Kafka消费者启动报错: Not authorized to access group
  14. phpMyadmin /scripts/setup.php Execute Arbitrary PHP Code Via A Crafted POST Request CVE-2010-3055
  15. 怎样调整好炒外汇心态
  16. KSQL:Apache Kafka的流式SQL
  17. Github项目分享——tabby
  18. 基于IC5000如何利用iSYSTEM winIDEA烧写+调试程序
  19. hive集群tez引擎执行任务卡住
  20. python判断一个月的天数_python日期列表中每个月的天数

热门文章

  1. 《此生未完成》痛句摘录(2)
  2. 端午前夕的班级小游戏
  3. 什么注解可以改变BigDecimal类型的字段返回的小数位数?
  4. alertmanager 告警恢复_Prometheus配置企业微信告警
  5. BigDecimal类的使用
  6. 等价关系和等价类_确定Java等价性的新时代?
  7. gradle配置_Gradle配置
  8. recorder_将Java Flight Recorder与OpenJDK 11一起使用
  9. 项目不能使用fn标签_无服务器,Java和FN项目的第一步
  10. kafka netty_惠而浦:使用Netty和Kafka的微服务