首页 > 其他分享 >命令模式

命令模式

时间:2022-11-11 19:56:15浏览次数:47  
标签:... void 模式 命令 Command bingBing public

命令模式

使用场景

我反复强调,设个非常重要!因为纵使你有十八般武器,不知道什么时候用也是白搭。从定义上我们就可以看出其可以解决的问题。

当需要将各种执行的动作抽象出来,使用时通过不同的参数来决定执行哪个对象
当某个或者某些操作需要支持撤销的场景
当要对操作过程记录日志,以便后期通过日志将操作过程重新做一遍时
当某个操作需要支持事务操作的时候
以上是命令模式可以胜任的场景,需要你在实践中不断摸索和体会。

uml图

image

可以看到命令模式有4个参与角色

Command
是一个接口,定义一个命令

ConcreteCommand
具体的执行命令,他们需要实现Command接口

Receiver
真正执行命令的角色,那些具体的命令引用它,让它完成命令的执行

Invoker
负责按照客户端的指令设置并执行命令,像命令的撤销,日志的记录等功能都要在此类中完成

项目实例

场景21世纪,人类社会的科技日新月异,狂人马斯克正在努力在2050年前将100万人类送往火星殖民。同时人类社会在其他方面也在努力创新,比如人工智能,这不最近有一家科技公司尽然制造出了高智慧机器人,还支持订制,真是太贴心了。王二狗很兴奋,乘着媳妇出差的时候,偷偷订制了两款:BingBing号与MiMi号。

今夜,王二狗就是整个小区那个最靓的仔,一切准备就绪,准备发车... 二狗随后会向机器人发出各种各样的指令,这个就很适合使用命令模式

声明命令接口

Command

/**
 * 命令接口,所有具体的命令都会实现此接口,Invoker只认识此接口
 *
 * 其实现类包含了可以执行自己的对象(receiver),以及执行时候需要的数据
 */
public interface Command {
    void execute();
}

构建那些可以具体完成命令的角色(Receiver)

构建一个BingBing号机器人

public class BingBingReceiver {

public void singSong(){
    System.out.println("落花满天蔽月光 借一杯附荐凤台上...");
}

public void playPiano(){
    System.out.println("随着BingBing纤细的双手在琴弦上来回撩拨,美妙的音乐响彻了整个房间...");
}
}

此处的BingBing号机器人只支持了两个功能:唱歌和弹琴,如果有想更进一步者,请自便...
构建一个MiMi号机器人

public class MiMiReceiver {
public void hotDance(){
    System.out.println("终日以文雅示人的大MIMI尽然也有她狂野的一面,只见她随着音乐疯狂的扭动,魅惑的表情更是让人想入非非,欲罢不能...");
}
}

此处指定MiMi号机器人只会跳辣舞

构建各种具体命令(ConcreteCommand)

构建一个唱歌命令,其要实现Command接口。因为只有BingBing机器人提供这个功能,所以我们要在这个命令内部使用BingBingReceiver 来具体执行。

public class SingSongCommand implements Command {
private BingBingReceiver bingBing;

public SingSongCommand(BingBingReceiver bingBing) {
    this.bingBing = bingBing;
}

@Override
public void execute() {
    bingBing.singSong();
}
}

构建一个弹琴命令,与前面唱歌命令类似

public class PlayPianoCommand implements Command {
private BingBingReceiver bingBing;

public PlayPianoCommand(BingBingReceiver bingBing) {
    this.bingBing = bingBing;
}

@Override
public void execute() {
    bingBing.playPiano();
}
}

二狗还想看辣舞,所以再构建一个跳辣舞命令。由于只有MiMi号机器人提供这个能力,所以此处的执行者就变成了MiMiReceiver

public class TiaoLaWuCommand implements Command {
    private YangMiReceiver daMiMi;
    private String duration;//跳舞的时长

    public TiaoLaWuCommand(YangMiReceiver daMiMi, String duration) {
        this.daMiMi = daMiMi;
        this.duration = duration;
    }

    @Override
    public void execute() {
        System.out.println(String.format("开始跳舞表演,时长为:%s", duration));
        daMiMi.hotDance();
    }
}

我们看到,此命令里面除了具体执行命令的MiMiReceiver,还包含了命令执行时需要的数据,例如跳舞时长。这也是命令模式需要注意的地方,具体的命令类里不止包含具体执行命令的那个对象,也包含相关数据。

构建命令的调用者 (Invoker)

器人和命令都准备好了,那么具体怎么发送呢?这就是Invoker的角色了。二狗买这两个机器人时还带了一个智能语音控制器,他通过这个控制器就可以发出各种命令了。

public class RobotInvoker {
    private final List<Command> sexRobotCommands = new ArrayList<>();

    public void clearCommand(){
        sexRobotCommands.clear();
    }

    //设置一套命令,不知道具体执行者是谁
    public void addCommands(Command command) {
        sexRobotCommands.add(command);
    }

    //执行系列命令
    public void executeCommand() {
        for (Command command : sexRobotCommands) {
            command.execute();
        }
    }
}

客户端使用

终于到了发车的时刻了。二狗兴奋的唤起了控制系统(RobotInvoker )喊道:来来,让bingbing先把琴弹起来,再把歌唱起来... 还有,让mimi来段辣舞,要那种让人欲罢不能的辣舞哦...

public class DogWang2Client {

    //享受陪伴机器人的服务
    public void enjoySexRobot() {
        //robot 控制系统,用户通过此系统来发出命令
        RobotInvoker invoker = new RobotInvoker();

        //生成唱歌弹琴命令
        BingBingReceiver bingBingReceiver = new BingBingReceiver();
        SingSongCommand singSongCommand = new SingSongCommand(bingBingReceiver);
        PlayPianoCommand playPianoCommand = new PlayPianoCommand(bingBingReceiver);
        //构建执行计划
        invoker.addCommands(singSongCommand);
        invoker.addCommands(playPianoCommand);
        //执行命令
        invoker.executeCommand();

        //生成跳舞命令
        ...

        //执行命令
        invoker.executeCommand();
    }
}

命令模式的要点如下

Command 接口非常简单,通常只有一个execute方法,如果要支持撤销操作的话,再加一个unexecute方法
每个具体的命令类内部封装了实际执行命令的那个类(Recevier),或者那些类,以及执行需要的数据
每个具体命令类只完成一个请求,有多少个请求就有多少个命令
Invoker类只认识接口Command,其他的都不认识
客户端类负责生成命令,并通过Invoker组装执行。

优缺点

优点
将调用操作与具体执行者解耦
你只管发出命令,至于命令由谁执行你不用关心。我们也可以随时将命令中具体执行者换掉,发出命令者是不知道的。例如你大老板交给经理一个任务,至于经理安排小张,还是小王来做,他根本就不关心

添加一个命令非常容易
很容易实现序列操作及实现回调系统
你把命令加到一个列表中,迭代执行就可以实现序列操作了。 因为Java不能将函数作为参数,此处我们可以将命令对象当做参数,而这个对象还可执行,所以就实现了回调功能。

缺点
类太多,每次增加一个命令,就要多加一个类。

标签:...,void,模式,命令,Command,bingBing,public
From: https://www.cnblogs.com/PythonOrg/p/16881584.html

相关文章

  • linux所有命令都无法使用,rm -f * 删除根目录
    【1】故障情况(1.1)误删文件在根目录下,有2个文件,node_exporter和node_exporter_start.sh我想把这2个文件都删掉,小心,生产环境 rm-fnode*要命了,多打了......
  • inux系统常用的150个命令/开发 运维 测试 安全
     线上查询命令和帮助2个man查看命令帮助命令的词典 help查看内置命令的帮助文件和目录18个ls-a-l查看目录的内容及属性 cd.当前目录..上级目录/根目......
  • C#设计模式之建造者模式
      原文网址:https://www.jb51.net/article/254976.htm场景:我们的冒险家,现在需要去武器商店买一把兵器,有刀和剑两种武器,冒险者可以告诉武器商人需要哪一种武器,然后武器商......
  • 新手必备的Linux命令
    新手必备的Linux命令,虽然平时大部分工作都是和Java相关的开发,但是每天都会接触Linux系统,尤其是使用了Mac之后,每天都是工作在黑色背景的命令行环境中.自己记忆力不好,......
  • 工厂模式
    工厂模式定义工厂类,及工厂方法,获取工厂里面的数据@Service@OrderpublicclassRuleFactory{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(R......
  • 软件设计模式白话文系列(六)代理模式
    1、描述代理模式属于结构型模式中的一种,通过对代理对象的调用来达到对原对象的增强、减弱作用。通过代理类的生成时机,我们将编译期就生成代理类的情况称之为静态代理模式,......
  • 常用Dos命令
    Dos命令#盘符切换E:D:#查看当前目录下的所有文件dir#切换目录cdcd/dD:进入D盘cd/dE:\文件路径进入E盘某文件cd..返回上一级cd目录名进入下一级......
  • iostat命令详解
    iostat命令格式:iostat[-c|-d][-k|-m][-t][-V][-x][device[...]......
  • Sqoop的简单使用案例和一些常用命令及参数
    Sqoop的简单使用案例1、导入数据在Sqoop中,“导入”概念指:从非大数据集群(RDBMS)向大数据集群(HDFS,HIVE,HBASE)中传输数据,叫做:导入,即使用import关键字。1.1、RDBMS到HDFS1)确定My......
  • Scala模式匹配
    1 switch与default等效的是捕获所有的case_模式。如果没有模式匹配,抛出MatchError,每个case中,不用break语句。可以在match中使用任何类型,而不仅仅是数字。varresult=0;......