用Java 8 Lambda表达式实现设计模式:命令模式
在这篇博客里,我将说明如何在使用 Java 8 Lambda表达式 的函数式编程方式 时实现 命令 设计模式 。命令模式的目标是将请求封装成一个对象,从对客户端的不同类型请求,例如队列或日志请求参数化,并提供相应的操作。命令模式是一种通用编程方式,该方式基于运行时决策顺序来执行方法。模式的参与者如下:
命令 : 声明用于执行操作的接口。
实体命令 :定义接收者对象和动作的绑定。
客户端 :创建实体命令实例并设置它的接收者。
调用者: 控制命令来执行请求。
接收者 :实际完成工作。
这些参与者之间的关系描述如下:

让我们看一个命令模式的具体例子,了解它是如何转换成lambda表达式的。假定我们有一个文件系统工具,所有动作都依赖它,例如打开文件,向文件写入和关闭文件。这可以实现宏功能 ,即一系列的操作可以被记录下来,之后作为一个单独操作执行。下面是我们的接收者。
- public interface FileSystemReceiver {
- void openFile();
- void writeFile();
- void closeFile();
- }
每个操作都是命令,例如 openFile 和 writeFile
。我们可以创建一个通用命令接口来适配这些不同的操作。让我们将接口命名为Action,因为在我们的情境下,它代表执行一个操作。所有命令对象都需要实现这个接口。
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 类。每个宏包含一个动作序列,该序列可以依次执行动作,它将作为调用者。这个类可以记录动作,并一起运行。我们可以将动作序列存储在列表中,然后反复地获取每个动作来执行。
- 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 = 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表达式整个模式得到大大的简化,因为我们完全可以废除这些类。然我们看看宏类(客户端)使用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)是命令模式常用的流行接口。这篇博客中,我试着阐述带Java 8 lambda表达式的命令模式。你可以看到使用lambda表达式,少了很多样板代码,从而让代码变得更整洁。
用Java 8 Lambda表达式实现设计模式:命令模式的更多相关文章
- Java 8 Lambda表达式10个示例【存】
PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...
- Java 8 lambda表达式示例
例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例.看一下Java 8之前的runna ...
- Java基础学习总结(44)——10个Java 8 Lambda表达式经典示例
Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Ja ...
- Java 8 Lambda表达式
Java 8 Lambda表达式探险 http://www.cnblogs.com/feichexia/archive/2012/11/15/Java8_LambdaExpression.html 为 ...
- 深入浅出 Java 8 Lambda 表达式
摘要:此篇文章主要介绍 Java8 Lambda 表达式产生的背景和用法,以及 Lambda 表达式与匿名类的不同等.本文系 OneAPM 工程师编译整理. Java 是一流的面向对象语言,除了部分简 ...
- Java 8 Lambda 表达式
Lambda 是啥玩意 简单来说,Lambda 就是一个匿名的方法,就这样,没啥特别的.它采用一种非常简洁的方式来定义方法.当你想传递可复用的方法片段时,匿名方法非常有用.例如,将一个方法传递给另外一 ...
- Java 8 Lambda 表达式详解
一.Java 8 Lambda 表达式了解 参考:Java 8 Lambda 表达式 | 菜鸟教程 1.1 介绍: Lambda 表达式,也可称为闭包,是推动 Java 8 发布的最重要新特性. La ...
- 02、Java的lambda表达式和JavaScript的箭头函数
前言 在JDK8和ES6的语言发展中,在Java的lambda表达式和JavaScript的箭头函数这两者有着千丝万缕的联系:本次试图通过这篇文章弄懂上面的两个"语法糖". 简介 ...
- Java 8 Lambda表达式学习和理解
Java 8 Lambda表达式和理解 说明:部分资料来源于网络 时间:20190704 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性.Lambda 允许把函数作为一 ...
随机推荐
- [Algorithm]线性表
一. 线性表基础算法 1.线性表插入操作 1 // 线性表插入操作(在第i(1≤i≤L.length+1)个位置上插入新元素elem) 2 bool InsertSeq( SeqList& L ...
- 关于CRTP(Curiously Recurring Template Prattern)的使用
在阅读frameworks/rs/cpp/util/RefBase.h之LightRefBase时,我记得<C++设计新思维>里对这种用法是有过介绍的,可是今天翻箱倒柜,怎么都找不到那本奇 ...
- Xgboost的sklearn接口参数说明
from xgboost.sklearn import XGBClassifier model=XGBClassifier(base_score=0.5, booster='gbtree', cols ...
- doges
dogse入门指南 Dogse作为游戏服务端引擎,目前只包含游戏服务端的核心部分,但这也是最核心的部分.它全部使用.net c#开发,充分兼顾了程序性能与代码编写的准确性与易用性,再加上以vs作为开发 ...
- [转]10分钟梳理MySQL知识点:揭秘亿级高并发数据库调优与最佳实践法则
转:https://mp.weixin.qq.com/s/RYIiHAHHStIMftQT6lQSgA 做业务,要懂基本的SQL语句: 做性能优化,要懂索引,懂引擎: 做分库分表,要懂主从,懂读写分离 ...
- [翻译]CURAND Libaray--Host API--(1)
原文来自:cuda curand toolkit document Translated by xingoo 如果有错误请联系:xinghl90@gmail.com 2Host API简述 使用hos ...
- github 的使用步骤
1. github是一个git项目托管网站 注册地址:https://github.com/signup/free 2. 安装git程序,执行下面操作 $ cd ~/.ssh //检查计算机ssh密钥 ...
- 「杂录」CQOI 2018 背板记
背景 经过一天天的等待,终于迎来了\(CQOI2018\),想想\(NOIp\)过后到现在,已经有了快要半年了,曾经遥遥无期,没想到时间一转眼就过去了-- 日志 \(Day0\) 因为明天就要考试了, ...
- centos操作---搭建环境 安装python
1.安装python3.6.2 安装依赖 yum -y groupinstall "Development tools" yum -y install zlib-devel bzi ...
- es6-01
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer ManufacturersAssociation)通过ECMA-262标准化的脚本程 ...