设计模式之旅18--命令模式

1. 定义

命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

命令模式

2. 使用场景

  • 需要抽象出待执行的动作,然后以参数的形式提供出来。替代过程设计中的回调机制。
  • 在不同的时刻指定、排列和执行请求。
  • 需要支持事务操作、取消功能、日志功能。
  • Android中的事件传递机制就使用到了命令模式。

3. 实现

以项目经理分别下发写代码、设计UI两条命令给程序员、视觉设计师为例子来实现命令模式。

接收者角色及其实现:

/**
 * 接收者角色:该角色就是干活的角色,命令传递到这里是应该被执行的。
 * 例子:程序员、视觉设计师的基类
 */
public abstract class Receiver {

    public abstract void doSomething();

}

/**
 * 例子:程序员
 */
public class ConcreteReceiver1 extends Receiver{

    @Override
    public void doSomething() {
        System.out.println("写代码");
    }
}

/**
 * 例子:视觉设计师
 */
public class ConcreteReceiver2 extends Receiver{

    @Override
    public void doSomething() {
        System.out.println("设计UI");
    }
}

命令角色及其实现:

/**
 * 命令角色:需要执行的所有命令都在这里声明。
 */
public abstract class Command {

    protected Receiver mReceiver;

    public Command(Receiver receiver) {
        this.mReceiver = receiver;
    }

    public abstract void execute();
}

/**
 * 例子:写代码的命令,下发给程序员
 */
public class ConcreteCommand1 extends Command {

    public ConcreteCommand1() {
        super(new ConcreteReceiver1());
    }

    public ConcreteCommand1(Receiver receiver) {
        super(receiver);
    }

    @Override
    public void execute() {
        this.mReceiver.doSomething();
    }
}

/**
 * 例子:设计UI的命令,下发给视觉设计师
 */
public class ConcreteCommand2 extends Command {

    public ConcreteCommand2() {
        super(new ConcreteReceiver2());
    }

    public ConcreteCommand2(Receiver receiver) {
        super(receiver);
    }

    @Override
    public void execute() {
        this.mReceiver.doSomething();
    }
}

调用者角色:

/**
 * 调用者角色:接收客户端的命令,并执行命令。
 * 例子:项目经理
 */
public class Invoker {

    private Command mCommand;

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

    public void action() {
        this.mCommand.execute();
    }
}

场景类:

public class Client {

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

        invoker.setCommand(new ConcreteCommand1());
        invoker.action();

        invoker.setCommand(new ConcreteCommand2());
        invoker.action();
    }
}

运行结果:

写代码
设计UI

4. 优点

  • 类间解耦。调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
  • 可扩展性。Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
  • 命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少Command子类的膨胀问题。

5. 缺点

  • 命令模式如果有N个命令Command的子类就有N个,类数量膨胀得非常大。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 4,003评论 1 15
  • 【学习难度:★★★☆☆,使用频率:★★★★☆】直接出处:命令模式梳理和学习:https://github.com/...
    BruceOuyang阅读 869评论 0 3
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,964评论 2 17
  • 目录 本文的结构如下: 什么是命令模式 为什么要用该模式 模式的结构 代码示例 优点和缺点 适用环境 模式应用 总...
    w1992wishes阅读 1,172评论 2 9
  • 2018年4月8日晴 今天老大放学要去踢足球,放学的时候只接了老二回家,回家后孩爸就开始辅导他写作业,说实话...
    mm阿章阅读 133评论 0 0