设计模式之 命令模式

命令模式(Command Pattern)是行为型设计模式之一,它将请求(或命令)封装成一个对象,从而使用户能够将请求发送者与请求接收者解耦。通过命令模式,调用操作的对象与执行操作的对象不直接关联,命令对象作为一个中介,传递请求和执行的责任,使得用户可以通过简单的调用接口来执行复杂的行为。

一、命令模式的基本概念

命令模式的核心思想是将请求封装为一个对象,通常这个对象包含了执行某个特定操作的必要信息和执行的逻辑。当请求被调用时,该命令对象会通知相应的执行者对象执行特定的操作。通过这种方式,命令的调用者和执行者之间无需直接交互,符合松耦合的设计原则。

1. 主要组成部分

命令模式通常包括以下几个关键角色:

  • Command(命令接口) :声明了执行命令的接口,通常包含一个execute()方法。

  • ConcreteCommand(具体命令类):实现了命令接口,封装了与特定请求相关的动作,并将请求转发给接收者对象。

  • Receiver(接收者类):执行与请求相关的具体操作。它知道如何执行与请求相关的操作。

  • Invoker(调用者类) :请求命令的发送者,它持有一个命令对象,并在适当的时候调用该命令对象的execute()方法。

  • Client(客户端):客户端创建一个具体的命令对象,并设置其接收者。客户端通常还会将该命令对象传递给调用者。

2. 工作原理

命令模式的工作原理是,当客户端希望执行某个操作时,它创建一个命令对象 (通常是ConcreteCommand的实例),并将该对象交给调用者 。调用者在适当的时候调用execute()方法,命令对象将请求委托给接收者进行实际的操作。由于所有的请求都通过命令对象封装并传递,调用者与接收者完全解耦。

二、命令模式的代码示例

命令接口
java 复制代码
public interface Command {
    void execute();
}
具体命令类
java 复制代码
public class OrderCommand implements Command{
    private Chef chef;
    private Order order;

    public OrderCommand(Chef chef, Order order) {
        this.chef = chef;
        this.order = order;
    }

    @Override
    public void execute() {
        System.out.println(order.getDiningTable()+"桌的餐");
        Set<String> foodNames = order.getFoodDesc().keySet();
        for (String foodName : foodNames) {
            chef.makeFood(order.getFoodDesc().get(foodName), foodName);
        }
    }
}
厨师
java 复制代码
public class Chef {
    public void makeFood(int number, String foodName){

        System.out.println("正在制作"+number+"份"+foodName);
    }
}
调用者类
java 复制代码
public class Waitor {
    private List<Command> commands = new ArrayList<>();

    public void setCommand(Command command){
        commands.add(command);
    }

    public void OrderUp(){
        commands.forEach(command -> {
            command.execute();
        });
    }
}
订单实体类
java 复制代码
public class Order {
    private int diningTable;
    Map<String,Integer> foodDesc = new HashMap<>();

    public int getDiningTable() {
        return diningTable;
    }

    public void setDiningTable(int diningTable) {
        this.diningTable = diningTable;
    }

    public Map<String, Integer> getFoodDesc() {
        return foodDesc;
    }

    public void setFoodDesc(String name,Integer num) {
        foodDesc.put(name, num);
    }
}
客户端代码
java 复制代码
public class Client {
    public static void main(String[] args) {
        Order order = new Order();
        order.setDiningTable(1);
        order.setFoodDesc("西红柿炒蛋", 2);
        order.setFoodDesc("拉面", 2);

        Command command = new OrderCommand(new Chef(), order);
        command.execute();
    }
}
输出结果

三、命令模式的优缺点

优点:
  1. 解耦请求者与执行者:调用者(Invoker)不需要知道具体的执行操作,只需要通过命令接口进行调用,避免了直接依赖具体的执行类。请求者和执行者之间的耦合度降低,系统更灵活。
  2. 支持命令的撤销与恢复:命令模式可以很方便地实现命令的撤销(Undo)和恢复(Redo)功能。通过保存历史命令,可以在需要时撤销之前的操作。
  3. 增加新的命令 :添加新的命令非常简单,只需要定义一个新的命令类并实现Command接口,不需要修改现有的类或调用者,符合开闭原则。
  4. 组合命令:多个命令可以组合成一个"复合命令",通过调用一个复合命令来依次执行多个操作,方便管理多个命令的执行。
缺点:
  1. 类的数量增加:命令模式会导致系统中增加很多命令类,特别是在命令种类多的情况下,可能会使系统变得较为复杂。
  2. 可能不必要的复杂度:对于一些简单的应用,命令模式可能会引入不必要的复杂度。在这些情况下,直接在客户端调用相关方法可能更加简洁。
  3. 客户端需要了解命令对象:虽然命令模式解耦了请求者与执行者,但客户端需要了解如何配置和使用命令对象,这可能增加一些学习和使用的成本。

四、命令模式的应用场景

命令模式特别适用于以下几种场景:

  1. GUI(图形用户界面)按钮操作

    在GUI应用中,用户点击按钮通常会触发一些行为,命令模式非常适合将按钮的操作封装为命令对象,解耦按钮与具体操作的实现。通过命令对象,可以将按钮的功能独立出来,方便修改和扩展。

  2. 事务管理

    对于需要管理多个操作的系统,命令模式可以用来记录每个操作(命令),并且在需要时执行或撤销这些操作。比如在事务处理系统中,可以使用命令模式来实现事务的提交、回滚操作。

  3. 宏命令

    如果某个操作需要执行一系列操作,可以通过将多个命令对象组合成一个复合命令(Macro Command),从而一次性执行一组操作。

  4. 日志系统

    在一些系统中,操作可能需要被记录(例如,用户在系统中执行了某个动作)。可以将每个操作封装成命令对象,并在执行时记录这些操作,甚至可以在以后重新执行。

  5. 远程操作系统

    在需要远程控制设备的场景中,命令模式可以帮助将操作封装成命令对象,通过网络发送命令对象,从而远程执行设备操作。

相关推荐
zzzhpzhpzzz1 小时前
设计模式——前端控制器模式
设计模式
forestsea1 小时前
【Java 解释器模式】实现高扩展性的医学专家诊断规则引擎
java·人工智能·设计模式·解释器模式
吃汉堡吃到饱4 小时前
【创建型设计模式】单例模式
单例模式·设计模式
小白不太白9504 小时前
设计模式之 备忘录模式
服务器·设计模式·备忘录模式
zzzhpzhpzzz4 小时前
设计模式——策略模式
设计模式·策略模式
入门到跑路4 小时前
【君正T31开发记录】8.了解rtsp协议及设计模式
网络协议·设计模式
小白不太白9504 小时前
设计模式之 解释器模式
java·设计模式·解释器模式
小白不太白9505 小时前
设计模式之 代理模式
设计模式·代理模式
吃汉堡吃到饱5 小时前
【创建型设计模式】工厂模式
设计模式