【设计模式-4.9】行为型——命令模式

发布于:2025-06-05 ⋅ 阅读:(16) ⋅ 点赞:(0)

说明:本文介绍行为型设计模式之一的命令模式

定义

命令模式(Command Pattern)是对命令的封装,每一个命令都是一个操作:请求方发出请求需要执行一个操作;接收方收到请求,并执行操作。命令模式解耦了请求方和接收方,请求方只需请求执行命令,不用关心命令怎样被接收、怎样被操作及是否被执行等。命令模式属于行为型设计模式。

(引自《设计模式就该这样学》P339)

灯泡开关设计

在实际生活中,发起命令和执行命令,大多是强绑定的,例如开车,一个操作对应就是一个反馈,但在程序设计上,考虑扩展性,就不能这样设计。

以灯泡开关为例,如下,是一个灯泡开关的设计

(灯泡,Bulb)

/**
 * 灯泡
 */
public class Bulb {

    /**
     * 开灯
     */
    public void on() {
        System.out.println("灯亮。。。");
    }

    /**
     * 关灯
     */
    public void off() {
        System.out.println("灯灭。。。");
    }
}

(灯泡开关,Switcher)

/**
 * 开关
 */
public class Switcher {

    /**
     * 定义灯泡
     */
    private Bulb bulb;

    public Switcher(Bulb bulb) {
        this.bulb = bulb;
    }


    /**
     * 按下按钮
     */
    public void buttonPush() {
        System.out.println("按下按钮");
        bulb.on();
    }

    /**
     * 弹起按钮
     */
    public void buttonPop() {
        System.out.println("弹起按钮");
        bulb.off();
    }
}

(客户端使用,Client)

public class Client {
    public static void main(String[] args) {
        Bulb bulb = new Bulb();
        Switcher switcher = new Switcher(bulb);

        // 开灯
        switcher.buttonPush();;
        // 关灯
        switcher.buttonPop();
    }
}

如下

在这里插入图片描述

分析,以上代码就是关于灯泡开关的强绑定设计,开关只能对灯泡使用,灯泡只能被这个开关开启/关闭。


使用命令模式改进,如下,

(先定义一个命令接口,Command)

/**
 * 命令接口
 */
public interface Command {

    /**
     * 执行
     */
    void execute();

    /**
     * 反向执行
     */
    void unexecute();
}

(灯泡命令,实现命令接口,BulbCommand)

/**
 * 灯泡命令
 */
public class BulbCommand implements Command {

    /**
     * 定义灯泡
     */
    private Bulb bulb;

    public BulbCommand(Bulb bulb) {
        this.bulb = bulb;
    }

    @Override
    public void execute() {
        System.out.println("按下按钮");
        bulb.on();
    }

    @Override
    public void unexecute() {
        System.out.println("弹起按钮");
        bulb.off();
    }
}

开关这里,不直接定义灯泡,而是定义命令,调用对应方法,如下

/**
 * 开关
 */
public class Switcher {

    /**
     * 定义命令
     */
    private Command command;

    /**
     * 设置命令
     */
    public void setCommand(Command command) {
        this.command = command;
    }


    /**
     * 按下按钮
     */
    public void buttonPush() {
        command.execute();
    }

    /**
     * 弹起按钮
     */
    public void buttonPop() {
        command.unexecute();
    }
}

客户端使用

public class Client {
    public static void main(String[] args) {
        // 创建开关
        Switcher switcher = new Switcher();
        
        // 创建灯泡
        Bulb bulb = new Bulb();

        // 创建灯泡命令
        Command switcherCommand = new BulbCommand(bulb);
        
        // 绑定
        switcher.setCommand(switcherCommand);
        
        // 执行
        switcher.buttonPush();
        
        // 反向执行
        switcher.buttonPop();
    }
}

执行,改造完成

在这里插入图片描述

分析可以发现,命令模式,通过新增一个接口(Command),实现了命令与操作的解耦。基于改造后的代码,扩展灯泡亮起的实现方式,可以新建一个BulbCommand类,如NewBulbCommand,写新的实现逻辑,使用的时候直接调用setCommand(newBulbCommand)方法即可,而扩展其他使用场景,也只需定义新的对象、新的命令即可,非常灵活。

使用场景

在《设计模式就该这样学》(P340)这本书中,提到命令模式适用于以下场景:

(1)现实语义中具备“命令”的操作(如命令菜单、Shell命令等)。

(2)请求的调用者和接收者需要解耦,使得调用者和接收者不直接交互。

(3)需要抽象出等待执行的行为,比如撤销(Undo)操作和恢复(Redo)等操作。

即等待多久后,默认执行的场景,如红帽的Linux操作系统和MacOS操作系统,点击关机,1分钟未确认自动执行关机

(4)需要支持命令宏(即命令组合操作)。

即执行操作的命令来源不是单一的,可能来自多个

总结

本文介绍了行为型设计模式中的命令模式,参考《设计模式就该这样学》、《秒懂设计模式》两书,灯泡开关设计是《秒懂设计模式》中的举例。


网站公告

今日签到

点亮在社区的每一天
去签到