19、设计模式之命令模式

命令模式

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

介绍

意图:

将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。

主要解决:

在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

何时使用:

在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

如何解决: 通过调用者调用接受者执行命令,顺序:调用者→命令→接受者。

关键代码:

定义三个角色:

  1. received 真正的命令执行对象
  2. Command
  3. invoker 使用命令对象的入口

应用实例:

struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command。

优点:

  1. 降低了系统耦合度。
  2. 新的命令可以很容易添加到系统中去。
  3. 命令模式结合其它模式更优秀
    3.1. 命令模式可以结合责任链模式,实现命令族解析任务;
    3.2. 结合模板方法模式,则可以减少command子类的膨胀问题;

缺点:

使用命令模式可能会导致某些系统有过多的具体命令类。

使用场景:

认为是命令的地方都可以使用命令模式,比如:

  1. GUI 中每一个按钮都是一条命令。
  2. 模拟 CMD。

注意事项:

系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式,见命令模式的扩展。

主要涉及到以下几个核心角色:

命令(Command):

定义了执行操作的接口,通常包含一个 execute 方法,用于调用具体的操作。

具体命令(ConcreteCommand):

实现了命令接口,负责执行具体的操作。它通常包含了对接收者的引用,通过调用接收者的方法来完成请求的处理。

接收者(Receiver):

知道如何执行与请求相关的操作,实际执行命令的对象。

调用者/请求者(Invoker):

发送命令的对象,它包含了一个命令对象并能触发命令的执行。调用者并不直接处理请求,而是通过将请求传递给命令对象来实现。

客户端(Client):

创建具体命令对象并设置其接收者,将命令对象交给调用者执行。

代码实现

考虑一个场景:

  1. 我们买了一套智能家电,有照明灯、风扇、冰箱、洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作。
  2. 这些智能家电来自不同的厂家,我们不想针对每一种家电都安装一个 App,分别控制,我们希望只要一个 app就可以控制全部智能家电。
  3. 要实现一个 app 控制所有智能家电的需要,则每个智能家电厂家都要提供一个统一的接口给 app 调用,这时 就可以考虑使用命令模式。
  4. 命令模式可将"动作的请求者"从"动作的执行者"对象中解耦出来.
  5. 在我们的例子中,动作的请求者是手机 app,动作的执行者是每个厂商的一个家电产品

定义 Receiver

java 复制代码
public interface Receiver {
    void on();

    void off();
}

定义具体的 Receiver,灯、冰箱

java 复制代码
/**
 * 灯
 */
public class Light implements Receiver{
    @Override
    public void on() {
        System.out.println("打开灯");
    }

    @Override
    public void off() {
        System.out.println("关闭灯");
    }
}

/**
 * 冰箱
 */
public class IceBox implements Receiver{

    @Override
    public void on() {
        System.out.println("冰箱打开");
    }

    @Override
    public void off() {
        System.out.println("冰箱关闭");
    }
}

抽象命令接口

java 复制代码
public interface Command {

    //执行动作(操作)
    void exec();
    //撤销动作(操作)
    void undo();
}

定义具体命令,灯、冰箱命令

java 复制代码
/**
 * 冰箱命令
 */
public class IceBoxCommand implements Command{
    private IceBox iceBox;

    public IceBoxCommand(IceBox iceBox) {
        this.iceBox = iceBox;
    }
    @Override
    public void exec() {
        iceBox.on();
    }

    @Override
    public void undo() {
        iceBox.off();
    }
}

/**
 * 灯命令
 */
public class LightCommand implements Command{

    private Light light;

    public LightCommand(Light light) {
        this.light = light;
    }

    @Override
    public void exec() {
        light.on();
    }

    @Override
    public void undo() {
        light.off();
    }
}

定义命令控制器

java 复制代码
/**
 * 遥控器
 */
public class Controller {
    private Map<String,Command> commands;

    public Controller(){
        commands = new java.util.HashMap<>();
    }

    public void addCommand(String name,Command command){
        commands.put(name,command);
    }

    public void onPressed(String name){
        commands.get(name).exec();
    }

    public void offPressed(String name){
        commands.get(name).undo();
    }
}

客户端

java 复制代码
public class Client {
    public static void main(String[] args) {
        //创建Receiver
        IceBox iceBox = new IceBox();
        Light light = new Light();
        //创建Command
        Command iceBoxCommand = new IceBoxCommand(iceBox);
        Command lightCommand = new LightCommand(light);
        //创建控制器
        Controller controller = new Controller();
        controller.addCommand("iceBox",iceBoxCommand);
        controller.addCommand("light",lightCommand);
        controller.onPressed("iceBox");
        controller.offPressed("iceBox");
        controller.onPressed("light");
        controller.offPressed("light");
    }
}
相关推荐
老蒋每日coding5 小时前
AI Agent 设计模式系列(十九)—— 评估和监控模式
人工智能·设计模式
会员果汁6 小时前
23.设计模式-解释器模式
设计模式·解释器模式
「QT(C++)开发工程师」13 小时前
C++设计模式
开发语言·c++·设计模式
茶本无香14 小时前
设计模式之七—装饰模式(Decorator Pattern)
java·设计模式·装饰器模式
漂洋过海的鱼儿1 天前
设计模式——EIT构型(三)
java·网络·设计模式
老蒋每日coding1 天前
AI Agent 设计模式系列(十八)—— 安全模式
人工智能·安全·设计模式
老蒋每日coding1 天前
AI Agent 设计模式系列(十六)—— 资源感知优化设计模式
人工智能·设计模式·langchain
老蒋每日coding1 天前
AI Agent 设计模式系列(十七)—— 推理设计模式
人工智能·设计模式
冷崖1 天前
桥模式-结构型
c++·设计模式
连山齐名1 天前
设计模式之一——堵塞队列
设计模式