命令设计模式

命令设计模式


1. 简单介绍

命令设计模式(Command)是一种行为型设计模式。该模式将一个请求、与具体的命令执行者封装成不同的对象。这种设计一方面可以对客户端的请求进行参数化,另一方面可以将命令的接收和执行很好的进行解耦。

2. 使用场景
  • 系统需要将请求调用者和请求的接收者接口,是的调用者和接收者互补交互
  • 系统需要在不同的时间指定请求、将请求排队和执行请求
  • 系统需要支持命令的撤销操作(undo)和恢复操作(redo)
  • 系统需要将一组操作组合在一起,即支持宏命令
3. 场景举例

程序开发中,经常使用的回调机制可以使用命令模式很好的解决。将回调方法(函数)封装成一个个命令(Command)。程序在回调时,调用相应的命令对象即可。

4. UML类图

命令模式UML类图

5. 具体实现

描述

  • 背景:Linux操作系统通过命令控制电脑的开机、重启
  • Command:命令封装类
  • RebootCommand:具体命令角色,重启命令
  • ShutdownCommand: 具体命令角色,关机电脑
  • Computer: 电脑,命令的具体执行者
  • Invoker:命令的发出者,对应Invoker角色

代码实现

Command.java

/**
 * Command:命令封装类
 */
public abstract class Command {

    /**
     * 聚合命令的具体执行者
     */
    protected Computer computer;

    public Command(Computer computer) {
        this.computer = computer;
    }

    /**
     * 命令执行接口方法
     */
    public abstract void execute();
}

RebootCommand.java

/**
 * RebootCommand:具体命令角色,重启命令
 */
public class RebootCommand extends Command {

    public RebootCommand(Computer computer) {
        super(computer);
    }

    /**
     * 重启命令的具体执行交给Computer实例对象
     */
    @Override
    public void execute() {
        computer.restart();
    }
}

ShutdownCommand.java

/**
 * ShutdownCommand: 具体命令角色,关机电脑
 */
public class ShutdownCommand extends Command {

    public ShutdownCommand(Computer computer) {
        super(computer);
    }

    /**
     * 关机命令的具体执行交给Computer实例对象
     */
    @Override
    public void execute() {
        computer.shutdown();
    }
}

Computer.java

/**
 * Computer: 电脑,命令的具体执行者
 */
public class Computer {

    /**
     * 执行RebootCommand命令
     */
    public void restart() {
        System.out.println("执行电脑重启命令:电脑正在重启");
    }

    /**
     * 执行ShutdownCommand命令
     */
    public void shutdown() {
        System.out.println("执行电脑关机命令:电脑正在关机");
    }
}

Invoker.java

/**
 * Invoker:命令的发出者,对应Invoker角色
 */
public class Invoker {

    /**
     * 存放待发出命令
     */
    private List<Command> commandList = new ArrayList<>();

    public void addCommand(Command command) {
        commandList.add(command);
    }

    /**
     * 发出执行
     */
    public void executeCommands() {
        for (Command command : commandList) {
            command.execute();
        }
    }
}

Client.java

/**
 * Client: 客户端
 */
public class Client {

    public static void main(String[] args) {

        // 1. 创建命令具体执行者:电脑
        Computer computer = new Computer();

        // 2. 创建、并发出命令
        Command rebootCommand = new RebootCommand(computer);
        Command shutdownCommand = new ShutdownCommand(computer);

        // 3. 添加到Invoker中
        Invoker invoker = new Invoker();
        invoker.addCommand(rebootCommand);
        invoker.addCommand(shutdownCommand);

        // 3. 执行指令
        // 4. 输出结果
        //     4.1 执行电脑重启命令:电脑正在重启
        //     4.2 执行电脑关机命令:电脑正在关机
        invoker.executeCommands();
    }
}
7. 源码展示

Spirng中的JdbcTemplate从接收SQL语句到执行SQL语句过程的实现,采用命令设计模式。其中,StatementCallback充当命令模式中的Command角色,其实现类充当ConcreteCommand角色。不同类型的SQL语句,会对应不同的StatementCallback具体实现类,其中包含QueryStatementCallbackExecuteStatementCallback等。JdbcTemplate类充当Invoker角色,负责接收待执行的SQL语句,根据不同的SQL类型,创建不同类型的StatementCallback,完成SQL的执行,真正的执行者是Statement的实现类,如:ClientStatement,充当Receiver角色。

StatementCallback.java

/**
 * 充当Command角色
 */
public interface StatementCallback<T> {
    // 不负责具体的执行,具体的执行由Statement来完成
    T doInStatement(Statement stmt) throws SQLException, DataAccessException;
}

JdbcTemplate.java

/**
 * 充当Invoker角色,负责接收待执行的SQL
 */
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
    public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
        Assert.notNull(sql, "SQL must not be null");
        Assert.notNull(rse, "ResultSetExtractor must not be null");
        if (logger.isDebugEnabled()) {
            logger.debug("Executing SQL query [" + sql + "]");
        }

        // Command的具体实现,接收到的SQL交给Statement执行
        class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
            @Override
            @Nullable
			public T doInStatement(Statement stmt) throws SQLException {
				ResultSet rs = null;
				try {
                    // SQL语句的真正执行者Statement,即Rceiver角色
					rs = stmt.executeQuery(sql);
					return rse.extractData(rs);
				}
				finally {
					JdbcUtils.closeResultSet(rs);
				}
			}
			@Override
			public String getSql() {
				return sql;
			}
		}
        // 此种类型,构造QueryStatementCallback命令
        // 具体的SQL执行,交给QueryStatementCallback对应的Statement
		return execute(new QueryStatementCallback());
	}
}

ClientStatement.java

/**
 * SQL的具体执行者,对应Receiver角色
 */
public class ClientStatement implements Statement, StatementCallbackInterface {
    // SQL的真正的执行方法
    public ResultSet executeQuery(String var1) throws SQLException {
        try {
            synchronized(this.connection_) {
                if (this.agent_.loggingEnabled()) {
                    this.agent_.logWriter_.traceEntry(this, "executeQuery", new Object[]{var1});
                }

                ClientResultSet var3 = this.executeQueryX(var1);
                if (this.agent_.loggingEnabled()) {
                    this.agent_.logWriter_.traceExit(this, "executeQuery", var3);
                }

                return var3;
            }
        } catch (SqlException var6) {
            throw var6.getSQLException();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
命令设计模式是一种行为型设计模式,它允许将请求封装成一个对象,从而使不同的请求能够在客户端之间进行参数化。下面是一个简单的命令设计模式的代码实现示例: ```python # 命令接口 class Command: def execute(self): pass # 具体命令类 class LightOnCommand(Command): def __init__(self, light): self.light = light def execute(self): self.light.on() class LightOffCommand(Command): def __init__(self, light): self.light = light def execute(self): self.light.off() # 接收者类 class Light: def on(self): print("灯已打开") def off(self): print("灯已关闭") # 调用者(遥控器)类 class RemoteControl: def __init__(self): self.commands = [] def add_command(self, command): self.commands.append(command) def execute_commands(self): for command in self.commands: command.execute() # 客户端代码 if __name__ == '__main__': light = Light() light_on_command = LightOnCommand(light) light_off_command = LightOffCommand(light) remote_control = RemoteControl() remote_control.add_command(light_on_command) remote_control.add_command(light_off_command) remote_control.execute_commands() ``` 在上面的示例中,我们定义了一个命令接口 `Command`,并实现了两个具体的命令类 `LightOnCommand` 和 `LightOffCommand`。这些具体命令类都实现了 `execute` 方法,用于执行相应的操作。`Light` 类是接收者类,它定义了真正执行操作的方法。`RemoteControl` 类是调用者类,它可以添加命令并执行它们。 在客户端代码中,我们创建了一个 `Light` 对象,并为它定义了打开和关闭的命令。然后,我们创建了一个遥控器对象 `RemoteControl`,并将命令添加到它里面。最后,我们调用 `execute_commands` 方法,执行所有添加的命令。 这就是一个简单的命令设计模式的代码实现示例。当然,实际应用可以更加复杂,可以根据具体需求进行扩展和修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值