设计模式(14)——命令 Command

本文详细介绍了命令模式的概念、适用场景及其实现方式,并通过C++代码示例展示了如何使用命令模式来解耦界面组件与功能模块。
目录:

设计模式学习笔记首页
设计模式(1)——抽象工厂 AbstractFactory
设计模式(2)——生成器 Builder
设计模式(3)——工厂方法 Factory Method
设计模式(4)——原型 Prototype
设计模式(5)——单例 Singleton
设计模式(6)——适配器 Adapter
设计模式(7)——桥接 Bridge
设计模式(8)——组合 Composite
设计模式(9)——装饰 Decorator
设计模式(10)——外观 Facade
设计模式(11)——享元 Flyweight
设计模式(12)——代理 Proxy
设计模式(13)——职责链 Chain Of Responsibility
设计模式(14)——命令 Command
设计模式(15)——解释器 Interpreter
设计模式(16)——迭代器 Iterator
设计模式(17)——中介者 Mediator
设计模式(18)——备忘录 Memento
设计模式(19)——观察者 Observer
设计模式(20)——状态 State
设计模式(21)——策略 Strategy
设计模式(22)——模板方法 Template Method
设计模式(23)——访问者 Visitor

十四、Command(命令模式,别名 Action 动作,Transaction 事务,对象行为型模式)

1. 意图:

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

2. 适用:

  1. 抽象出待执行的动作以参数化某对象。
  2. 在不同的时刻指定、排列和执行请求。
  3. 支持取消操作。
  4. 支持修改日志。
  5. 用构建在原语操作上的高层操作构造一个系统。

3. 类图:

image

4. 中间层思考:

  命令模式在界面组件和功能模块之间提供了一个中间层 Command,界面组件不再直接调用功能模块,而是调用 Command 的抽象方法。这样将界面组件与功能模块解耦,界面组件可以灵活切换要实现的功能,功能模块的改动也不会对界面组件有影响。

5. 命令模式与适配器模式

  命令模式的类图和适配器模式的类图很像,它们做的事情都是制造了一个中间层, 提供给系统统一的调用接口,封装了真正干活的实体。它们的差异还是在于使用意图,命令模式是为了命令的复用和灵活切换,而适配器模式是为了在新旧接口之间做兼容。

6. C++实现:

  1. 首先编写一个命令接口 Command,包含一个执行方法 Excute()
  2. 编写一个接收者类 Receiver,包含一个具体的执行动作方法 Action()
  3. 编写命令接口的具体的实现类 ConcreteCommandhas-a 一个接收者对象 _rev,由ConcreteCommand的构造函数初始化
  4. 编写调用者类 Invokerhas-a 一个命令对象 _cmd,包含一个调用方法 Invoke(),方法体调用 _cmd 的 Excute(),Exuete() 执行具体接收者如 _rev 的 Action()
Command.h
//Command.h
#pragma once
class Receiver;

class Command {
public:
    virtual ~Command();
    virtual void Excute() = 0;
protected:
    Command();
private:
};

class ConcreteCommand : public Command {
public:
    ConcreteCommand(Receiver* rev);
    ~ConcreteCommand();
    void Excute();
protected:
private:
    Receiver* _rev;
};
Command.cpp
//Command.cpp
#include "Command.h"
#include "Receiver.h"

#include <iostream>

ConcreteCommand::ConcreteCommand(Receiver * rev){
    this->_rev = rev;
}

ConcreteCommand::~ConcreteCommand(){
    delete _rev;
}

void ConcreteCommand::Excute(){
    this->_rev->Action();
}

Command::~Command(){}

Command::Command(){}
Invoker.h
//Invoker.h
#pragma once

class Command;

class Invoker {
public:
    Invoker(Command* cmd);
    ~Invoker();
    void Invoke();
protected:
private:
    Command* _cmd;
};
Invoker.cpp
//Invoker.cpp
#include "Invoker.h"
#include "Command.h"

Invoker::Invoker(Command * cmd){
    this->_cmd = cmd;
}

Invoker::~Invoker(){
    delete _cmd;
}

void Invoker::Invoke()
{
    this->_cmd->Excute();
}
Receiver.h
//Receiver.h
#pragma once

class Receiver {
public:
    Receiver();
    ~Receiver();
    void Action();
protected:
private:
};
Receiver.cpp
//Receiver.cpp
#include "Receiver.h"
#include <iostream>

Receiver::Receiver() {}
Receiver::~Receiver() {}
void Receiver::Action() {
    std::cout << "Receiver action......" << std::endl;
}
main.cpp
//main.cpp
#include "Command.h"
#include "Invoker.h"
#include "Receiver.h"
#include <iostream>
using namespace::std;

int main(int argc, char* argv[]) {
    Receiver* rev = new Receiver();
    Command* cmd = new ConcreteCommand(rev);
    Invoker* inv = new Invoker(cmd);
    inv->Invoke();
    return 0;
}
### Java 中命令模式(Command Pattern)的实现与示例 #### 1. 命令模式的核心概念 命令模式是一种行为型设计模式,其核心目标是将请求封装为一个对象,从而使不同类型的请求可以被参数化处理。这种方式不仅实现了请求发送者和接收者的解耦[^2],还提供了诸如撤销、重做以及日志记录等功能的支持。 #### 2. 核心角色及其职责 以下是命令模式的主要组成部分及其作用: - **命令接口(Command Interface)**: 定义了一个 `execute()` 方法用于执行命令,还可以定义 `undo()` 方法用于撤销命令。 - **具体命令(Concrete Command)**: 实现了命令接口,并绑定了具体的接收者与其操作方法。 - **接收者(Receiver)**: 执行实际的操作逻辑。 - **调用者(Invoker)**: 负责触发命令的执行,通常会持有某个命令对象的引用。 - **客户端(Client)**: 创建具体命令对象并将其与相应的接收者关联起来[^4]。 #### 3. 遥控器控制家电的经典示例 ##### 步骤 1:定义命令接口 ```java public interface Command { void execute(); } ``` ##### 步骤 2:实现接收者(家电类) 假设我们有一个简单的电灯作为接收者: ```java public class Light { public void turnOn() { System.out.println("Light is ON"); } public void turnOff() { System.out.println("Light is OFF"); } } ``` ##### 步骤 3:实现具体命令类 针对上述电灯的功能,分别创建打开和关闭的具体命令: ```java public class TurnOnLightCommand implements Command { private final Light light; public TurnOnLightCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOn(); } } public class TurnOffLightCommand implements Command { private final Light light; public TurnOffLightCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOff(); } } ``` ##### 步骤 4:实现调用者(遥控器) 遥控器作为一个调用者,负责存储当前的命令并通过按钮触发该命令: ```java public class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { if (command != null) { command.execute(); } else { System.out.println("No command set."); } } } ``` ##### 步骤 5:客户端调用 最后,在客户端中完成整个流程的组装和测试: ```java public class Client { public static void main(String[] args) { // 接收者 Light livingRoomLight = new Light(); // 具体命令 Command onCommand = new TurnOnLightCommand(livingRoomLight); Command offCommand = new TurnOffLightCommand(livingRoomLight); // 调用者 RemoteControl remote = new RemoteControl(); // 设置并执行开灯命令 remote.setCommand(onCommand); remote.pressButton(); // 输出: Light is ON // 设置并执行关灯命令 remote.setCommand(offCommand); remote.pressButton(); // 输出: Light is OFF } } ``` #### 4. 支持宏命令(批量操作) 为了支持更复杂的场景,比如一次执行多个命令,可以通过引入宏命令来实现。下面是一个简单示例: ##### 步骤 1:定义宏命令类 ```java import java.util.ArrayList; import java.util.List; public class MacroCommand implements Command { private List<Command> commands = new ArrayList<>(); public void addCommand(Command command) { commands.add(command); } public void removeCommand(Command command) { commands.remove(command); } @Override public void execute() { for (Command cmd : commands) { cmd.execute(); } } } ``` ##### 步骤 2:客户端使用宏命令 ```java public class ClientWithMacro { public static void main(String[] args) { Light kitchenLight = new Light(); Light bedroomLight = new Light(); Command kitchenOn = new TurnOnLightCommand(kitchenLight); Command kitchenOff = new TurnOffLightCommand(kitchenLight); Command bedroomOn = new TurnOnLightCommand(bedroomLight); Command bedroomOff = new TurnOffLightCommand(bedroomLight); MacroCommand macroCommand = new MacroCommand(); macroCommand.addCommand(kitchenOn); macroCommand.addCommand(bedroomOn); RemoteControl remote = new RemoteControl(); remote.setCommand(macroCommand); remote.pressButton(); // 同时开启厨房和卧室灯光 } } ``` #### 5. 总结 通过以上实例可以看出,命令模式在分离请求发起方与执行方的同时,也增强了系统的灵活性和可维护性。然而需要注意的是,过多的命令可能会导致系统变得臃肿,因此应权衡利弊合理应用。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值