使用函数式实现命令模式

栏目: 后端 · 发布时间: 6年前

内容简介:Command模式是对象式很容易转换到函数式的一个模式,让我们看一个简单的例子来说明它是如何工作的。首先,有必要定义一个建模命令的接口:提供此Command接口的不同实现。例如,假设我们需要不同的命令来处理消息 - 您可以使用一个命令来记录消息:将消息保存在文件中是另外一个命令实现:

Command模式是对象式很容易转换到函数式的一个模式,让我们看一个简单的例子来说明它是如何工作的。首先,有必要定义一个建模命令的接口:

<b>interface</b> Command {
    <b>void</b> run();
}

提供此Command接口的不同实现。例如,假设我们需要不同的命令来处理消息 - 您可以使用一个命令来记录消息:

<b>public</b> <b>class</b> Logger implements Command {
    <b>public</b> <b>final</b> String message;
 
    <b>public</b> Logger( String message ) {
        <b>this</b>.message = message;
    }
 
    @Override
    <b>public</b> <b>void</b> run() {
        System.out.println(<font>"Logging: "</font><font> + message);
    }
}
</font>

将消息保存在文件中是另外一个命令实现:

<b>public</b> <b>class</b> FileSaver implements Command {
    <b>public</b> <b>final</b> String message;
 
    <b>public</b> FileSaver( String message ) {
        <b>this</b>.message = message;
    }
 
    @Override
    <b>public</b> <b>void</b> run() {
        System.out.println(<font>"Saving: "</font><font> + message);
    }
}
</font>

电子邮件发送:

<b>public</b> <b>class</b> Mailer implements Command {
    <b>public</b> <b>final</b> String message;
 
    <b>public</b> Mailer( String message ) {
        <b>this</b>.message = message;
    }
 
    @Override
    <b>public</b> <b>void</b> run() {
        System.out.println(<font>"Sending: "</font><font> + message);
    }
}
</font>

一个可以执行以多个命令的对象:

<b>public</b> <b>class</b> Executor {
    <b>public</b> <b>void</b> execute(List<Command> tasks) {
        <b>for</b> (Command task : tasks) {
            task.run();
        }
    }
}

最后可以将我们想要运行的命令添加到List中并通过Executor执行它们:

List<Command> tasks = <b>new</b> ArrayList<>();
tasks.add(<b>new</b> Logger( <font>"Hi"</font><font> ));
tasks.add(<b>new</b> FileSaver( </font><font>"Cheers"</font><font> ));
tasks.add(<b>new</b> Mailer( </font><font>"Bye"</font><font> ));
 
<b>new</b> Executor().execute( tasks );
</font>

Gang of Four书中建议我们将函数(要执行的动作)包装到对象(执行这些动作的命令)中,然而,这种间接级别除了允许我们将函数适合于严格面向对象的编程风格。但是,随着 Java 8中lambda的引入,现在可以无缝地混合函数和面向对象的范例,我们可以以更紧凑的方式重新思考前一个例子。

首先,请注意我们不需要定义Command接口:Runnable,它存在于Java的第一个版本中,它有一个抽象方法,具有与Command 1相同的签名。前3命令实现可以通过3个函数以更简洁的方式替换,在Java 8中可以使用3个静态方法实现:

<b>public</b> <b>static</b> <b>void</b> log(String message) {
    System.out.println(<font>"Logging: "</font><font> + message);
}
 
<b>public</b> <b>static</b> <b>void</b> save(String message) {
    System.out.println(</font><font>"Saving: "</font><font> + message);
}
 
<b>public</b> <b>static</b> <b>void</b> send(String message) {
    System.out.println(</font><font>"Sending: "</font><font> + message);
}
</font>

使用函数式思维重新思考命令实现带来了显着提高代码信号/噪声比的好处,其中信号是函数体,而噪声是用于表示该函数的所有附加代码作为方法一个东西。甚至Executor类也可以用单行静态方法替换,将List of Runnables作为参数:

<b>public</b> <b>static</b> <b>void</b> execute(List<Runnable> tasks ) {
    tasks.forEach( Runnable::run );
}

我们的函数可以添加到List中,并像以前一样执行。

List<Runnable> tasks = <b>new</b> ArrayList<>();
tasks.add(() -> log(<font>"Hi"</font><font>));
tasks.add(() -> save(</font><font>"Cheers"</font><font>));
tasks.add(() -> send(</font><font>"Bye"</font><font>));
 
execute( tasks );
</font>

Java编译器自动转换不带参数的lambda,并调用void静态方法,作为Runnable接口的匿名实现,从而让Runnables类型的集合Collection中容纳它们,而之前是需要实现Command接口的。


以上所述就是小编给大家介绍的《使用函数式实现命令模式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Cracking the Coding Interview

Cracking the Coding Interview

Gayle Laakmann McDowell / CareerCup / 2015-7-1 / USD 39.95

Cracking the Coding Interview, 6th Edition is here to help you through this process, teaching you what you need to know and enabling you to perform at your very best. I've coached and interviewed hund......一起来看看 《Cracking the Coding Interview》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具