# 命令模式

# 概念

命令模式一种行为型模式,它将请求封装为对象,使请求的发送者与接收者解耦。通过参数化请求、支持队列、日志记录、撤销/重做等功能,增强系统的灵活性和扩展性。

# 作用

1.解耦请求发送者与接收者:调用者仅依赖抽象命令接口,无需知道具体操作实现。

2.支持动态功能扩展:新增命令时无需修改现有代码,符合开闭原则。

3.实现操作回滚:通过undo()方法支持撤销功能。

4.增强控制能力:可组合多个命令形成宏命令,或实现延迟执行、事务管理。

# 场景

1.需要解耦请求发起方与执行方。

2.要求支持命令队列、批量执行或事务回滚。

3.需实现撤销/重做、日志记录等高级功能。

4.希望动态指定或组合多个请求操作。

# 举例

// 命令接口
interface Command {
    void execute();
    void undo();
}
// 接收者(库存管理)
class PhoneInventory {
    private int stock = 10;

    public void buyPhones(int quantity) {
        stock += quantity;
        System.out.println("采购成功,当前库存:" + stock);
    }

    public void sellPhones(int quantity) {
        if(stock >= quantity) {
            stock -= quantity;
            System.out.println("销售成功,当前库存:" + stock);
        } else {
            System.out.println("库存不足,销售失败");
        }
    }
}
// 具体命令:采购
class BuyCommand implements Command {
    private PhoneInventory inventory;
    private int quantity;

    public BuyCommand(PhoneInventory inventory, int quantity) {
        this.inventory = inventory;
        this.quantity = quantity;
    }

    @Override
    public void execute() {
        inventory.buyPhones(quantity);
    }

    @Override
    public void undo() {
        inventory.sellPhones(quantity);
    }
}
// 具体命令:销售
class SellCommand implements Command {
    private PhoneInventory inventory;
    private int quantity;

    public SellCommand(PhoneInventory inventory, int quantity) {
        this.inventory = inventory;
        this.quantity = quantity;
    }

    @Override
    public void execute() {
        inventory.sellPhones(quantity);
    }

    @Override
    public void undo() {
        inventory.buyPhones(quantity);
    }
}
// 调用者(命令处理器)
class OrderProcessor {
    private List<Command> commands = new ArrayList<>();

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

    public void processOrders() {
        for(Command cmd : commands) {
            cmd.execute();
        }
        commands.clear();
    }
}
// 客户端使用
public class Main {
    public static void main(String[] args) {
        PhoneInventory inventory = new PhoneInventory();
        OrderProcessor processor = new OrderProcessor();

        processor.addCommand(new BuyCommand(inventory, 5));
        processor.addCommand(new SellCommand(inventory, 3));

        processor.processOrders();
    }
}

# 反例

不使用命令模式时,直接调用接收者方法:

public class WithoutCommandPattern {
    public static void main(String[] args) {
        PhoneInventory inventory = new PhoneInventory();
        inventory.buyPhones(5);
        inventory.sellPhones(3);
    }
}

缺陷说明:

1.紧耦合:调用方直接依赖PhoneInventory的具体方法,若方法名或参数变更(如buyPhones改为purchasePhones),所有调用代码需修改。

2.扩展困难:新增returnPhones功能时,必须修改客户端代码调用新方法,违反开闭原则。

3.无法撤销:需手动记录操作历史并反向调用(如销售3台后需再采购3台),维护成本高。

4.缺乏灵活性:无法实现命令队列、延迟执行或事务管理,所有操作立即执行且无法批量控制。

# 原理

命令模式通过Command接口定义执行和撤销方法,将操作封装为对象。调用者(如OrderProcessor)维护命令队列,通过execute()触发操作,undo()实现回滚。接收者(如PhoneInventory)负责具体业务逻辑,与调用者解耦。

# 缺点

1.类膨胀:每个操作需对应一个具体命令类,增加系统复杂度。

2.间接层过多:需多层级对象协作(命令对象、接收者、调用者),可能降低运行效率。

3.学习成本:开发者需理解命令封装与解耦机制,初期理解难度较高。

总结

命令模式通过封装请求为对象,实现发送者与接收者的彻底解耦,支持撤销、队列、组合命令等高级功能。适用于需要灵活控制操作流程的场景(如事务管理、操作历史回滚)。反观直接调用方式,虽简单高效,但难以应对复杂需求变更和扩展。选择时需权衡功能需求与系统复杂度。



微信公众号

QQ交流群
原创网站开发,偏差难以避免。

如若发现错误,诚心感谢反馈。

愿你倾心相念,愿你学有所成。

愿你朝华相顾,愿你前程似锦。