在这篇博客里,我将说明如何在使用 Java 8 Lambda表达式 的函数式编程方式 时实现 命令 设计模式 。命令模式的目标是将请求封装成一个对象,从对客户端的不同类型请求,例如队列或日志请求参数化,并提供相应的操作。命令模式是一种通用编程方式,该方式基于运行时决策顺序来执行方法。模式的参与者如下:

命令   : 声明用于执行操作的接口。
实体命令 :定义接收者对象和动作的绑定。
客户端 :创建实体命令实例并设置它的接收者。
调用者: 控制命令来执行请求。
接收者 :实际完成工作。

这些参与者之间的关系描述如下:

让我们看一个命令模式的具体例子,了解它是如何转换成lambda表达式的。假定我们有一个文件系统工具,所有动作都依赖它,例如打开文件,向文件写入和关闭文件。这可以实现宏功能 ,即一系列的操作可以被记录下来,之后作为一个单独操作执行。下面是我们的接收者。

  1. public interface FileSystemReceiver {
  2. void openFile();
  3. void writeFile();
  4. void closeFile();
  5. }

每个操作都是命令,例如 openFile 和 writeFile

。我们可以创建一个通用命令接口来适配这些不同的操作。让我们将接口命名为Action,因为在我们的情境下,它代表执行一个操作。所有命令对象都需要实现这个接口。

public interface Action {
    public void perform();
}
现在,让我们为每个操作实现Action接口。所有这些类需要做的就是调用FileReceiver的一个方法,并将这个调用封装到Action接口中。在封装操作后,使用适当的类命名规范来命名这些类 。 因此,openFile方法对象的类称为 OpenFile 。

  1. public class OpenFile implements Action {
  2. private final FileReceiver fileReceiver;
  3. public OpenFile(FileReceiver fileReceiver) {
  4. this.fileReceiver = fileReceiver;
  5. }
  6. public void perform() {
  7. fileReceiver.openFile();
  8. }
  9. }

现在,我们实现 Macro 类。每个宏包含一个动作序列,该序列可以依次执行动作,它将作为调用者。这个类可以记录动作,并一起运行。我们可以将动作序列存储在列表中,然后反复地获取每个动作来执行。

  1. public class Macro {
  2. private final List actions;
  3. public Macro() {
  4. actions = new ArrayList<>();
  5. }
  6. public void record(Action action) {
  7. actions.add(action);
  8. }
  9. public void run() {
  10. actions.forEach(Action::perform);
  11. }
  12. }

当填充宏对象时,我们可以添加每个命令的实例,这些实例也会被记录在宏对象里。现在简单的运行宏对象,每个命令将依次执行。我们的客户端代码如下。

  1. Macro macro = new Macro();
  2. macro.record(new OpenFile(fileReceiver));
  3. macro.record(new WriteFile(fileReceiver));
  4. macro.record(new CloseFile(fileReceiver));
  5. macro.run();

如果你跟着我的思路读到这里,你会好奇lambda表达式如何适配这些的。实际上,所有命令类,例如OpenFile、WriteFile和CloseFile,其实只是lambda表达式想打破它们的封装。这些命令类只是在类之间传递。使用lambda表达式整个模式得到大大的简化,因为我们完全可以废除这些类。然我们看看宏类(客户端)使用lambda表达式代替命令类的效果。

  1. Macro macro = new Macro();
  2. macro.record(() -> fileReceiver.openFile());
  3. macro.record(() -> fileReceiver.writeFile());
  4. macro.record(() -> fileReceiver.closeFile());
  5. macro.run();

如果能够意识到每个lambda表达式都在执行一个单独的方法调用,可以进一步改进。因此,可以直接使用方法引用。

  1. Macro macro = new Macro();
  2. macro.record(fileReceiver::openFile);
  3. macro.record(fileReceiver::writeFile);
  4. macro.record(fileReceiver::closeFile);
  5. macro.run();

命令模式易于扩展,新的动作方法可以被添加到接收者中来创建新的命令实现,这样不需要改变任何客户端代码。JDK中的 Runnable 接口(java.lang.Runnable)是命令模式常用的流行接口。这篇博客中,我试着阐述带Java 8 lambda表达式的命令模式。你可以看到使用lambda表达式,少了很多样板代码,从而让代码变得更整洁。

最新文章

  1. 【Java每日一题】20161209
  2. Java开发环境的配置与Hello World
  3. ElasticSearch之一——索引
  4. 两种方法解决tomcat的 Failed to initialize end point associated with ProtocolHandler [&quot;http-apr-8080&quot;]
  5. Account Team使用说明
  6. 1020: 部分A+B
  7. LoadRunner安装包(性能测试工具分享)
  8. jquery ajax提交json格式的数据,后台接收并显示各个属性
  9. 201521123038 《Java程序设计》 第十三周学习总结
  10. springdata 一对多配置
  11. P1438 无聊的数列
  12. 我的github地址 https://github.com/1010de/Test.git
  13. 8.21 :odd??:nth-of-type??
  14. static 构造函数的认识
  15. Kafka 处理器客户端介绍
  16. vcenter建立cluster
  17. 自己写操作系统---bootsector篇
  18. Java 8 Lambda实现原理分析
  19. mysql各种连接总结
  20. 大数据测试之ETL测试工具和面试常见的问题及答案

热门文章

  1. DjVu、PDF中的隐藏文本
  2. c#百分比计算
  3. GTK+介绍
  4. 温故而知新_C语言_递归
  5. KDevelop4调试pcl一直读取不到.pcd文件
  6. Jquery学习理解 (课堂)
  7. jmeter - 录制web网页
  8. Python——用socket和线程实现全双工收发数据
  9. Spring IOC机制使用SpEL
  10. NOIWC2019游记