一起来学设计模式之命令模式

504 阅读8分钟

前言

目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~

本节给大家讲一下设计模式中的命令模式,并结合实际业务场景给大家讲解如何使用~

本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~

命令模式

命令模式(Command Pattern)是一种行为型设计模式,它允许将请求封装成对象,从而使您可以将不同的请求参数化,将请求排队或记录请求日志,以及支持可撤销操作。在这个模式中,请求被封装成一个对象,并在发送者和接收者之间解耦。命令模式允许在不更改现有客户端代码的情况下添加新命令

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

  • Command(命令):定义了执行操作的接口。
  • ConcreteCommand(具体命令):实现了Command接口并定义了具体的操作。
  • Invoker(调用者):发出请求的对象,它不知道具体执行的操作。
  • Receiver(接收者):执行操作的对象。
// 定义一个命令接口
public interface Command {
    void execute();
}

// 定义具体的命令类
public class LightOnCommand implements Command {
    private Light light;

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

    public void execute() {
        light.turnOn();
    }
}

// 定义接收者类
public class Light {
    public void turnOn() {
        System.out.println("Light is on");
    }

    public void turnOff() {
        System.out.println("Light is off");
    }
}

// 定义调用者类
public class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建接收者对象
        Light light = new Light();

        // 创建具体命令对象并设置其接收者
        Command lightOnCommand = new LightOnCommand(light);

        // 创建调用者对象并设置其命令
        RemoteControl remoteControl = new RemoteControl();
        remoteControl.setCommand(lightOnCommand);

        // 调用者发出请求,命令对象执行具体操作
        remoteControl.pressButton();
    }
}

在上面的示例中,LightOnCommand类是具体的命令类,它实现了Command接口,并将具体的操作(即打开灯)封装在execute()方法中。Light类是接收者类,它包含了打开和关闭灯的方法。RemoteControl类是调用者类,它发出请求并执行命令。Client类是客户端代码,它使用这些类来演示命令模式的使用。

最佳实践

电商平台在订单处理过程中可以使用命令模式,将订单操作封装成命令对象,从而实现请求的排队、记录日志以及支持撤销操作等功能。

以下是一个简单的电商平台订单处理系统的命令模式示例:

// 定义一个命令接口
public interface OrderCommand {
    void execute();
    void undo();
}

// 定义具体的命令类,比如创建订单、取消订单、支付订单等
public class CreateOrderCommand implements OrderCommand {
    private Order order;

    public CreateOrderCommand(Order order) {
        this.order = order;
    }

    public void execute() {
        order.create();
    }

    public void undo() {
        order.cancelCreate();
    }
}

public class CancelOrderCommand implements OrderCommand {
    private Order order;

    public CancelOrderCommand(Order order) {
        this.order = order;
    }

    public void execute() {
        order.cancel();
    }

    public void undo() {
        order.uncancel();
    }
}

public class PayOrderCommand implements OrderCommand {
    private Order order;

    public PayOrderCommand(Order order) {
        this.order = order;
    }

    public void execute() {
        order.pay();
    }

    public void undo() {
        order.unpay();
    }
}

// 定义接收者类,即订单类
public class Order {
    private int orderId;
    private String status;

    public void create() {
        System.out.println("订单创建成功");
        this.status = "Created";
    }

    public void cancelCreate() {
        System.out.println("取消订单创建");
        this.status = "";
    }

    public void cancel() {
        System.out.println("订单取消成功");
        this.status = "Cancelled";
    }

    public void uncancel() {
        System.out.println("订单取消被撤销");
        this.status = "Created";
    }

    public void pay() {
        System.out.println("订单支付成功");
        this.status = "Paid";
    }

    public void unpay() {
        System.out.println("订单支付被撤销");
        this.status = "Created";
    }

    public String getStatus() {
        return status;
    }
}

// 定义调用者类,即订单处理器类
public class OrderProcessor {
    private List<OrderCommand> commandList = new ArrayList<>();

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

    public void processCommands() {
        for (OrderCommand command : commandList) {
            command.execute();
        }
        commandList.clear();
    }

    public void undoLastCommand() {
        if (commandList.size() > 0) {
            OrderCommand lastCommand = commandList.get(commandList.size() - 1);
            lastCommand.undo();
            commandList.remove(lastCommand);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建订单对象
        Order order = new Order();

        // 创建具体命令对象并设置其接收者
        OrderCommand createOrderCommand = new CreateOrderCommand(order);
        OrderCommand cancelOrderCommand = new CancelOrderCommand(order);
        OrderCommand payOrderCommand = new PayOrderCommand(order);

        // 创建订单处理器对象并设置其命令
        OrderProcessor orderProcessor = new OrderProcessor();
        orderProcessor.addCommand(createOrderCommand);
        orderProcessor.addCommand(cancelOrderCommand);
        orderProcessor.addCommand(payOrderCommand

        // 处理命令
        orderProcessor.processCommands();

        // 输出订单状态
        System.out.println("订单状态: " + order.getStatus());

        // 撤销最后一个命令
        orderProcessor.undoLastCommand();

        // 输出订单状态
        System.out.println("撤销后订单状态: " + order.getStatus());
    }

}

输出:

订单创建成功
订单取消成功
订单支付成功
订单状态: Paid
撤销后订单状态: Paid

在这个示例中,订单处理器类 OrderProcessor 充当了调用者角色,将具体的订单操作命令 OrderCommand 对象添加到一个命令列表中,并在需要的时候执行它们。同时,OrderProcessor 类还提供了一个 undoLastCommand() 方法,用于撤销最后一个执行的命令。

具体的订单操作命令实现了 OrderCommand 接口,并将订单对象 Order 设置为它们的接收者。当执行命令时,相应的操作将在订单对象中被执行,比如 CreateOrderCommand 将调用 Order 对象的 create() 方法, CancelOrderCommand 将调用 Order 对象的 cancel() 方法等等。

通过使用命令模式,我们可以很方便地实现对订单操作的排队、记录日志以及支持撤销操作等功能,而无需修改订单对象的代码。同时,通过将订单操作封装成命令对象,我们也可以很容易地扩展订单处理系统,添加新的订单操作命令。

结束语

设计模式其实并不难,大家在学习的时候一定要在理解的基础上去写代码,不要去背代码。下节给大家讲解释器模式~

本着把自己知道的都告诉大家,如果本文对您有所帮助,点赞+关注鼓励一下呗~

相关文章

项目源码(源码已更新 欢迎star⭐️)

Kafka 专题学习

项目源码(源码已更新 欢迎star⭐️)

ElasticSearch 专题学习

项目源码(源码已更新 欢迎star⭐️)

往期并发编程内容推荐

推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)

博客(阅读体验较佳)