基本介绍

在软件设计中,我们经常需要向某些对象发送一些请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需要在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。

命令模式(Command Pattern)可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。

命令模式将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。

模式结构

  • Invoker:调用者,发送命令

  • Receiver:接收者,接收命令

  • Command:抽象命令类,定义了所有的命令

  • ConcreteCommand:具体命令类,调用接收者的操作

举例说明

现有许多家电(电灯、电视机、空调....),每个家电都有自己的控制装置,如果需要控制它们,需要逐个开启、逐个关闭,这时候,如果有一个万能遥控器(如下如所示),操作不同的家电只需要按对应的按钮即可,如何使用命令模式实现?

1、创建电灯的命令接收者

public class LightReceiver {
public void on() {
System.out.println("电灯打开了");
} public void off() {
System.out.println("电灯关闭了");
}
}

2、创建抽象的命令接口

public interface Command {
/**
* 执行命令
*/
void execute(); /**
* 撤销命令
*/
void undo();
}

3、创建电灯的开启、关闭命令类,实现命令接口

public class LightOnCommand implements Command {
private LightReceiver lightReceiver; public LightOnCommand(LightReceiver lightReceiver) {
this.lightReceiver = lightReceiver;
} @Override
public void execute() {
lightReceiver.on();
} @Override
public void undo() {
lightReceiver.off();
}
}
public class LightOffCommand implements Command {
private LightReceiver lightReceiver; public LightOffCommand(LightReceiver lightReceiver) {
this.lightReceiver = lightReceiver;
} @Override
public void execute() {
lightReceiver.off();
} @Override
public void undo() {
lightReceiver.on();
}
}

4、创建空的命令类,用于初始化按钮

public class NullCommand implements Command {
@Override
public void execute() { } @Override
public void undo() { }
}

5、创建命令调用者

public class RemoteController {
/**
* 操作对象的个数
*/
private static final int COUNT = 5;
/**
* 开启命令组
*/
Command[] onCommands;
/**
* 关闭命令组
*/
Command[] offCommands;
/**
* 执行撤销的命令
*/
Command undoCommand; /**
* 初始化
*/
public RemoteController() {
onCommands = new Command[COUNT];
offCommands = new Command[COUNT];
for (int i = 0; i < COUNT; i++) {
onCommands[i] = new NullCommand();
offCommands[i] = new NullCommand();
}
} /**
* 设置按钮
*/
public void setCommand(int no, Command onCommand, Command offCommand) {
onCommands[no] = onCommand;
offCommands[no] = offCommand;
} /**
* 按下开按钮
*/
public void pressOnButton(int no) {
onCommands[no].execute();
//记录按钮,以便撤销
undoCommand = onCommands[no];
} /**
* 按下关按钮
*/
public void pressOffButton(int no) {
offCommands[no].execute();
//记录按钮,以便撤销
undoCommand = offCommands[no];
} /**
* 按下撤销按钮
*/
public void pressUndoButton(int no) {
if (undoCommand != null) {
undoCommand.undo();
}
}
}

6、测试类

public class Client {
@Test
public void testLight() {
//创建命令接收者
LightReceiver lightReceiver = new LightReceiver();
//创建电灯的一组操作(开和关)
LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);
//创建命令调用者
RemoteController remoteController = new RemoteController();
//设置命令
remoteController.setCommand(0, lightOnCommand, lightOffCommand);
//执行命令
System.out.println("----按下开灯按钮----");
remoteController.pressOnButton(0);
System.out.println("----按下关灯按钮----");
remoteController.pressOffButton(0);
System.out.println("----按下撤销按钮----");
remoteController.pressUndoButton(0);
}
}

7、运行结果

----按下开灯按钮----
电灯打开了
----按下关灯按钮----
电灯关闭了
----按下撤销按钮----
电灯打开了

8、如果再添加一个电视机,不需要改动任何已有的代码,添加 TvReceiverTvOnCommandTvOffCommand 这几个类即可。

模式分析

设计模式 - 命令模式详解及其在JdbcTemplate中的应用的更多相关文章

  1. 设计模式 - 模板方法模式详解及其在Spring中的应用

    基本介绍 模板方法模式(Template Method Pattern)也叫模板模式,它在一个抽象类中公开定义了执行它的方法的模板,它的字类可以按需重写方法实现,但调用将以抽象类中定义的方式进行. 简 ...

  2. 设计模式 - 迭代器模式详解及其在ArrayList中的应用

    基本介绍 迭代器模式(Iterator Pattern)是 Java 中使用最多的一种模式,它可以顺序的访问容器中的元素,但不需要知道容器的内部细节 模式结构 Iterator(抽象迭代器):定义遍历 ...

  3. 虚拟机中linux系统常用命令解释及vim3种命令模式详解

    1.man man 加上一个命令可以打开此命令具体使用方法,方便我们更好的了解新命令的使用(下图为我输入命令“man ls”虚拟机界面) 2.cd  切换目录 cd ..(返回上一级目录) cd ~( ...

  4. JS设计模式——工厂模式详解

    它的领域中同其它模式的不同之处在于它并没有明确要求我们使用一个构造器.取而代之,一个工厂能提供一个创建对象的公共接口,我们可以在其中指定我们希望被创建的工厂对象的类型. 简单工厂模式:使用一个类(通常 ...

  5. Java设计模式-策略模式详解

    前言 在软件领域中,设计模式作为一种经典的开发实践常常需要我们去深入的理解,而策略模式作为设计模式的一种,使用频率也是相对来说比较高的,在Java中,当我们学习TreeSet集合的时候,就采用了经典的 ...

  6. Javascript设计模式之装饰者模式详解篇

    一.前言: 装饰者模式(Decorator Pattern):在不改变原类和继承的情况下动态扩展对象功能,通过包装一个对象来实现一个新的具有原对象相同接口的新的对象. 装饰者模式的特点: 1. 在不改 ...

  7. JavaScript严格模式详解

    转载自阮一峰的博客 Javascript 严格模式详解   作者: 阮一峰 一.概述 除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict m ...

  8. install 命令用法详解

    install 命令用法详解 http://man.linuxde.net/install install命令的作用是安装或升级软件或备份数据,它的使用权限是所有用户.install命令和cp命令类似 ...

  9. Mysql数据库导入命令Source详解

    Mysql数据库导入命令Source详解 几个常用用例: 1.导出整个数据库 mysqldump -u 用户名 -p 数据库名 > 导出的文件名 mysqldump -u root -p dat ...

随机推荐

  1. n次方

    1.问题描述 计算 an 2.算法分析 先将 n 变一变,寻找新的计算路径.预处理就是变治法的根本. 如果单纯循环执行 n 次相乘,那么时间复杂度为 O(n).可以利用二进制幂大大改进效率. 主要思路 ...

  2. python—os模块

     os模块(操作目录) 1 import os 2 os.rename('旧','新') #修改文件名 3 os.remove('') #删除文件 4 print(os.listdir('.')) # ...

  3. Ubuntu复制粘贴快捷键

    复制:[Ctrl+Insert] 粘贴:[Shitf+Insert]

  4. Unity 游戏框架搭建 2019 (十八~二十) 概率函数 & GameObject 显示、隐藏简化 & 第二章 小结与快速复习

    在笔者刚做项目的时候,遇到了一个需求.第一个项目是一个跑酷游戏,而跑酷游戏是需要一条一条跑道拼接成的.每个跑道的长度是固定的,而怪物的出现位置也是在跑道上固定好的.那么怪物出现的概率决定一部分关卡的难 ...

  5. php源码的编译

    本片文章主要介绍windows下的php源码的编译. 1.1 编译环境 软件 环境 操作系统 Windows 7 专业版 32bit Visual studio 2012 专业版 PHP 5.5.2. ...

  6. STL之vector常用函数笔记

    STL之vector常用函数笔记 学会一些常用的vector就足够去刷acm的题了 ps:for(auto x:b) cout<<x<<" ";是基于范围的 ...

  7. .net core 跨平台开发 微服务架构 基于Nginx反向代理 服务集群负载均衡

    1.概述 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客 ...

  8. Jmeter 压力测试笔记(3)--脚本调试/签名/cookie/提升吞吐量/降低异常率/提升单机并发性能

    import XXXsign.Openapi2sign;---导入jar包中的签名方法 String str1 = "12121"; ---需要被签名的字段:向开发了解需要哪些哪些 ...

  9. 关于微信小程序的一点经验

    2018年的11月份,自己做微信小程序相关的项目已经有四个月,这四个月自己走过很多弯路,也学到了不少经验,下面就一一总结: 一,微信小程序的radio组件是可以改变按钮样式的(比如大小,颜色等等) 改 ...

  10. String 对象-->判断是否相等

    1.定义和用法 == 值相等 === 绝对相等(值和类型都相等) 举例: var str = '8' var str1 = 8 console.log(str == str1) console.log ...