设计模式之命令模式

一、介绍

命令模式(Command Pattern),属于行为型设计模式。指的是把方法调用封装成命令,然后执行该命令。目的是为了将类中的各个方法抽出来,形成独立的类,且该类只有一个方法execute(),调用该类的execute()方法就等同于调用原类中对应的方法。

更接地气的说法是,A类中有B、C、D三个方法,使用命令模式,将这三个方法抽出来形成独立的类:BCommondCCommondDCommond,这三个类都实现Command接口中的execute()方法,方法的具体实现与A类中的B、C、D三个方法相同。

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

二、命令模式中的角色

在命令模式中,我们需要将一个类中的方法都提取出来,将它们封装成对应的命令类(XXXCommand),通过调用这些命令类的执行方法execute()来运行对应的逻辑,因此我们可以声明一个命令的抽象接口Command,由不同的具体命令实现该抽象接口。因此,命令模式中包含两个角色:抽象命令接口Command、命令接口实现类XXXCommand

  • 抽象命令接口Command

    定义一个命令的基本功能方法execute(),用于执行命令。代码如下所示

    public interface Command {
    
        void execute();
    }
    
  • 命令接口实现类XXXCommand

    实现抽象命令接口Command,对接口中的execute()方法进行具体实现。代码如下所示

    public class XXXCommand implements Command{
    
        @Override
        public void execute() {
            System.out.println("执行XXX命令对应的逻辑...");
        }
    }
    
  • 调用命令的客户端类CommandClient

    在客户端中,通过对命令对象的声明,进而调用该对象的execute()方法以执行对应的命令。

    public class CommandClient {
    
        public static void main(String[] args) {
            XXXCommand command = new XXXCommand();
            command.execute();
        }
    }
    

下面是命令模式的通用UML类图

在这里插入图片描述

三、案例

没办法,一说到命令俺就只能想到打仗,那就不妨以李云龙攻打平安县城为例吧。哈哈哈。

李云龙作为三八六旅独立团团长,可以向他指挥的士兵下达任何作战命令,比如:进攻(attack)拉意大利炮(cannon)开炮(fire),对于这三个命令来说,李云龙相当于命令模式中的客户端,通过下达这几个命令,他的士兵就会执行相应的命令。

因此结合案例,我们通过代码对其进行演示。

1. 命令的抽象接口Command

每一个命令都需要被执行,因此将其抽象为接口类Command,并声明其执行方法execute()

public interface Command {

    void execute();
}

2. 进攻AttackCommand

新建进攻命令AttackCommand,并实现命令接口Command定义的execute()方法。

当李云龙对着战士们说:兄弟们冲啊。此时就下达了进攻命令。

public class AttackCommand implements Command{
    @Override
    public void execute() {
        System.out.println("士兵进行冲锋进攻。。。");
    }
}

3. 意大利炮cannonCommand

与**进攻命令(AttackCommand)**相似,实现命令接口,实现方法逻辑。

当李云龙对着二营长说:**二营长,你他娘的意大利炮呢?**此时就下达了拿出意大利炮的命令。

public class CannonCommand implements Command{
    @Override
    public void execute() {
        System.out.println("二营长将意大利炮拉出来了。。。");
    }
}

4. 开炮FireCommand

与**进攻命令(AttackCommand)**相似,实现命令接口,实现方法逻辑

当李云龙对着战士说:开炮~~~,这就是开炮命令,战士则需要向平安县城城楼开炮了。

public class FireCommand implements Command{
    @Override
    public void execute() {
        System.out.println("士兵向平安县城城楼开炮。。。");
    }
}

5. 李云龙LiYunLong

李云龙作为独立团指挥官,负责下达各种作战命令。

public class LiYunLong {

    public static void main(String[] args) {
        System.out.println("李云龙:兄弟们冲啊");
        AttackCommand attackCommand = new AttackCommand();
        attackCommand.execute();
        System.out.println();

        System.out.println("李云龙:二营长,你他娘的意大利炮呢?");
        CannonCommand cannonCommand = new CannonCommand();
        cannonCommand.execute();
        System.out.println();

        System.out.println("李云龙:开炮~~~");
        FireCommand fireCommand = new FireCommand();
        fireCommand.execute();
    }
}

6. 运行案例

运行以上案例,模拟李云龙下达作战命令后,得到以下输出

在这里插入图片描述

四、优缺点

使用命令模式后,我们可以总结出以下优缺点

优点:

  • 降低了系统耦合度
  • 新的命令可以很容易添加到系统中去。

缺点:

  • 导致系统有过多的具体命令类。每一个命令都需要新建一个类。


纸上得来终觉浅,绝知此事要躬行。

————————我是万万岁,我们下期再见————————

命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使得请求的发送者和接收者解耦。在命令模式中,请求以命令的形式包裹在对象中,并传递给调用对象。调用对象寻找可以处理该命令的合适的对象,并将命令传递给相应的对象,该对象执行命令。 在C语言中,可以使用函数指针来实现命令模式。具体步骤如下: 1. 定义一个命令接口,该接口包含一个执行命令的方法。 2. 创建具体的命令类,实现命令接口,并在执行方法中调用相应的函数。 3. 创建一个调用者类,该类包含一个命令对象,并提供一个执行命令的方法。 4. 在调用者类中,将命令对象传递给相应的对象,并调用命令对象的执行方法。 下面是一个简单的示例代码: ```c #include <stdio.h> // 定义命令接口 typedef struct { void (*execute)(void); } Command; // 创建具体的命令类 typedef struct { Command command; void (*function)(void); } ConcreteCommand; void concreteCommand_execute(void) { printf("执行具体的命令\n"); } // 创建调用者类 typedef struct { Command *command; void (*setCommand)(Command *command); void (*executeCommand)(void); } Invoker; void invoker_setCommand(Command *command) { Invoker *invoker = (Invoker *)command; invoker->command = command;} void invoker_executeCommand(void) { Invoker *invoker = (Invoker *)invoker->command; invoker->command->execute(); } int main() { // 创建具体的命令对象 ConcreteCommand concreteCommand; concreteCommand.command.execute = concreteCommand_execute; concreteCommand.function = concreteCommand_execute; // 创建调用者对象 Invoker invoker; invoker.setCommand((Command *)&concreteCommand); invoker.executeCommand(); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

理想万岁万万岁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值