设计模式 —— 命令模式(Command Pattern)

原创 2016年05月29日 18:34:53

命令模式(Command Pattern)

概念:

概述:在软件设计中,我们经常会遇到某些对象发送请求,然后某些对象接受请求后执行,但发送请求的对象可能并不知道接受请求的对象是谁,执行的是什么动作。此时可通过 命令模式 来实现,让发送者和接受者完全的松耦合,这样可大大增强程序的灵活性。


定义:命令模式 将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

组成:

命令模式

Client(客户):负责创建一个具体的命令(Concrete Command)
Invoker(调用者):调用者持有一个命令对象,并在某个时刻调用命令对象的 execute() 方法。
Command(命令接口):包含命令对象的 execute() 方法和 undo() 方法。
ConcreteCommand(具体命令):实现命令接口。包括两个操作,执行命令和撤销命令。
Receiver(接收者):接受命令并执行。


例子:

现在比较火的小米手机,可以当作遥控器控制多种不同的家电,手机发送命令,不同的电器接收到后执行。

命令模式

Command 类

public interface Command {
    public void execute();
    public void undo();
}

开灯命令

public class LightOnCommand implements Command {
    private Light light;

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

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

    public void undo() {
        light.off();
    }
}

开电视命令

public class TVOnCommand implements Command {
    private TV tv;

    public TVOnCommand(TV tv) {
        this.tv = tv;
    }

    public void execute() {
        tv.on();
    }

    public void undo() {
        tv.off();
    }
}

家用电器接口类

public interface HouseholdAppliances {
    public void on();
    public void off();
}

电视类

public class TV implements HouseholdAppliances {
    public void on() {
        System.out.println("the TV on");
    }

    public void off() {
        System.out.println("the TV off");
    }
}

电灯类

public class Light implements HouseholdAppliances{
    public void on() {
        System.out.println("the light on");
    }

    public void off() {
        System.out.println("the light off");
    }
}

手机控制器类

public class MiPhone {
    ArrayList commands;

    public MiPhone() {
        commands = new ArrayList();
    }

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

    public void onButtonWasPushed(int slot) {
        ((Command)commands.get(slot-1)).execute();
    }

    public static void main(String[] args) {
        MiPhone miPhone = new MiPhone();
        //创建电器
        Light light = new Light();
        TV tv = new TV();
        //创建命令
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        TVOnCommand tvOnCommand = new TVOnCommand(tv);
        //给小米手机设置命令
        //设置第一个按钮为开灯
        miPhone.setCommand(lightOnCommand);
        //设置第二个按钮为开电视
        miPhone.setCommand(tvOnCommand);

        //开灯
        miPhone.onButtonWasPushed(1);
        //开电视
        miPhone.onButtonWasPushed(2);
    }
}

运行结果:

命令模式


适用场景

  • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
  • 系统需要在不同的时间指定请求、将请求排队(如:线程池+工作队列)和执行请求。
  • 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
  • 系统需要将一组操作组合在一起,即支持宏命令。

优缺点:

优点:

  • 降低系统的耦合度:Command模式将调用操作的对象与知道如何实现该操作的对象解耦。
  • Command是头等的对象。它们可像其他的对象一样被操纵和扩展。
  • 组合命令:你可将多个命令装配成一个组合命令,即可以比较容易地设计一个命令队列和宏命令。一般说来,组合命令是Composite模式的一个实例。
  • 增加新的Command很容易,因为这无需改变已有的类。
  • 可以方便地实现对请求的Undo和Redo。

缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

更多用途:

  • 宏命令模式:命令模式 加 组合模式,我们可以将多个命令组合到一起来实现命令的批处理。
  • 队列请求:将命令排成一个队列打包,一个个调用 execute 方法,如线程池的任务队列,线程不关心任务队列中是读 IO 还是计算,只取出命令后执行,接着进行下一个。
  • 日志请求:某些应用需要我们将所有的动作记录在日志中,然后在系统死机等情况出现时,重新调用这些动作恢复到之前的状态。如数据库事务。

参考:

《Head first 设计模式》

设计模式 ( 十三 ) 命令模式Command(对象行为型)

版权声明:free, open, share

命令模式(Command Pattern)(一):命令模式介绍

一、意图              将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。 二、适用性 ...
  • jialinqiang
  • jialinqiang
  • 2013年05月18日 23:16
  • 2817

浅谈JAVA设计模式之——命令模式(Command)

一、概述 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。 二、适用性 1.抽象出待执行的动作以参数化某对象。 2.在不同的时刻指...
  • l1028386804
  • l1028386804
  • 2015年05月08日 00:22
  • 3821

设计模式之命令模式(Command)

命令模式(Command)把请求封装成一个对象,使请求能够存储更多的信息拥有更多的能力。命令模式同样能够把请求的发送者和接收者解耦,但它不关心请求将以何种方式被处理。命令模式经常与职责链模式(Chai...
  • u010064842
  • u010064842
  • 2013年08月13日 13:22
  • 1039

我所理解的设计模式(C++实现)——命令模式(Command Pattern)

概述:         我们去餐厅吃饭,我们是通过服务员来点菜,具体是谁来做这些菜和他们什么时候完成的这些菜,其实我们都不知道。抽象之,“菜单请求者”我们和“菜单实现者”厨师,2者之间是松耦合的,我们...
  • LCL_data
  • LCL_data
  • 2013年06月12日 21:45
  • 16447

我所理解的设计模式(C++实现)——命令模式(Command Pattern)

概述:         我们去餐厅吃饭,我们是通过服务员来点菜,具体是谁来做这些菜和他们什么时候完成的这些菜,其实我们都不知道。抽象之,“菜单请求者”我们和“菜单实现者”厨师,2者之间是松耦合的,我...
  • lixingying567
  • lixingying567
  • 2015年06月07日 09:45
  • 248

设计模式——命令模式 (Command Pattern)

命令模式:目的是解除调用类与接收者类之间的耦合。 命令模式的构成: 1、Client做初始化,实例化所有将要执行的Commend对象,和提供对应功能的Receiver(即TV)对象。 ...
  • u013038616
  • u013038616
  • 2014年10月20日 17:16
  • 347

设计模式(15)——命令模式(Command Pattern)

一、前言 之前一直在忙于工作上的事情,关于设计模式系列一直没更新,最近项目中发现,对于设计模式的了解是必不可少的,当然对于设计模式的应用那更是重要,可以说是否懂得应用设计模式在项目中是衡量一个程序员...
  • qq4267002
  • qq4267002
  • 2016年03月03日 11:31
  • 190

java设计模式——命令模式(Command Pattern)

概述:        在软件开发中,我们经常需要向某些对象发送请求(调用其中的某个或某些方法),但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,此时,我们特别希望能够以一种松耦合的方式来设...
  • yj_android_develop
  • yj_android_develop
  • 2016年08月22日 16:53
  • 162

C#设计模式——命令模式(Command Pattern)

一、概述 通常来说,“行为请求者”与“行为实现者”是紧耦合的。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这些情况下,将“行为请求者”与“行...
  • ottokira
  • ottokira
  • 2012年05月19日 11:15
  • 120

深入浅出设计模式——命令模式(Command Pattern)

转载自:https://www.cnblogs.com/Bobby0322/p/4195240.html 模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的...
  • IAMoldpan
  • IAMoldpan
  • 2017年12月27日 14:24
  • 29
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式 —— 命令模式(Command Pattern)
举报原因:
原因补充:

(最多只允许输入30个字)