设计模式之命令模式

本文深入解析了命令模式,包括概念、结构、优缺点及常见应用场景。通过实例演示了如何在Java中实现,并结合源码分析了Runnable接口如何体现该模式。

Command design pattern

命令模式的概念、命令模式的结构、命令模式的优缺点、命令模式的使用场景、命令模式的实现示例、命令模式的源码分析


1、命令模式的概念

  命令模式,即将请求封装成一个对象,使发出请求的责任和执行请求的责任分离开。这样两者之间通过命令对象进行沟通,方便讲命令对象进行存储、传递、调用和管理。

2、命令模式的结构

  • 抽象命令:定义执行命令的行为。
  • 实现者/接受者:命令的实现者或接受者,真正执行命令的对象。任何类都可以成为一个接受者,只要它能够实现命令所要求的功能。
  • 具体命令:实现抽象命令,持有接受者的引用,通过委托调用接受者执行命令的方法来实现命令的行为。
  • 调用者/请求者:即命令请求,命令发起者,持有命令对象的引用,它可以持有多个命令,即可以一次性发出多个命令。它是客户端真正出发命令并要求命令执行的地方,也就是相当于使用命令对象的入口。

command-class

3、命令模式的优缺点

  • 优点:
    • 降低系统的耦合度。即降低命令请求者与执行者的耦合度。
    • 满足开闭原则,增加命令或删除命令不影响其它类,扩展灵活。
    • 可实现宏命令,命令模式可与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
    • 方便实现 Undo 和 Redo 操作,命令模式可与备忘录模式结合,实现命令的撤销和恢复。
  • 缺点:
    • 导致系统有过多的具体命令类,增加系统复杂度。

4、命令模式的使用场景

  • 当需要讲请求者调用者和请求接受者解耦时。
  • 当需要在不同的时间指定请求,将请求排队和执行请求。
  • 当需要支持命令的撤销操作和恢复操作时。

5、命令模式的实现示例

接受者:

public class Receiver {

    /**
     * 命令接受者执行命令
     * @param name
     */
    public void attack(String name) {
        System.out.println(name);
    }
}

抽象命令:

public interface Command {

    /**
     * 执行命令
     */
    void execute();
}

具体命令:

public class ZedCommand implements Command {

    private String name;

    private Receiver receiver;

    public ZedCommand(String name, Receiver receiver) {
        this.name = name;
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.attack(this.name);
    }
}

调用者:

public class Invoker {

    private List<Command> commands;

    public Invoker() {
        this.commands = new ArrayList<>();
    }

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

    /**
     * 发出命令
     */
    public void commands() {
        for (Command command : this.commands) {
            command.execute();
        }
    }
}

测试:

public class CommandTest {

    public static void main(String[] args) {
        Invoker invoker = new Invoker();

        Receiver receiver = new Receiver();

        invoker.addCommand(new ZedCommand("禁奥义·瞬狱影杀阵", receiver));
        invoker.addCommand(new ZedCommand("影奥义·分身", receiver));
        invoker.addCommand(new ZedCommand("影奥义·鬼斩", receiver));
        invoker.addCommand(new ZedCommand("影奥义·诸刃", receiver));
        invoker.addCommand(new ZedCommand("影奥义·分身", receiver));
        invoker.addCommand(new ZedCommand("影忍法·灭魂劫", receiver));
        invoker.addCommand(new ZedCommand("禁奥义·瞬狱影杀阵", receiver));

        invoker.commands();
    }
}

测试结果:

禁奥义·瞬狱影杀阵
影奥义·分身
影奥义·鬼斩
影奥义·诸刃
影奥义·分身
影忍法·灭魂劫
禁奥义·瞬狱影杀阵

6、命令模式的源码分析

  jdk 中的 Runnable 接口的设计就是一个典型的命令模式。Runnable 接口担当命令角色,Thread 则是调用者,start 方法就是命令执行方法。

// 抽象命令
public interface Runnable {
  	// 执行命令
    public abstract void run();
}
public class Thread implements Runnable {
  	// 持有命令的引用
  	private Runnable target;
  public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

    private native void start0();
}

  通过源码可以发现,其在发出命令调用时会调用一个本地方法 start0(),开启一个县城。而接受者是对外开放的,即程序员可以自己定义接受者。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红衣女妖仙

行行好,给点吃的吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值