设计模式(14)--Command(命令模式)--行为型
作者QQ:1095737364 QQ群:123300273 欢迎加入!
1.模式定义:
2.模式特点:
3.使用场景:
4.模式实现:

(1)客户端(Client)角色:
public class Client {
public static void main(String[] args) {
//创建接收者
Receiver receiver = new Receiver();
//创建命令对象,设定它的接收者
Command command = new ConcreteCommand(receiver);
//创建请求者,把命令对象设置进去
Invoker invoker = new Invoker(command);
//执行方法
invoker.action();
}
}
(2)命令(Command)角色:
public interface Command {
/**
* 执行方法
*/
void execute();
}
(3)具体命令(ConcreteCommand)角色:
public class ConcreteCommand implements Command {
//持有相应的接收者对象
private Receiver receiver = null;
/**
* 构造方法
*/
public ConcreteCommand(Receiver receiver){
this.receiver = receiver;
}
@Override
public void execute() {
//通常会转调接收者对象的相应方法,让接收者来真正执行功能
receiver.action();
}
}
(4)请求者(Invoker)角色:
public class Invoker {
/**
* 持有命令对象
*/
private Command command = null;
/**
* 构造方法
*/
public Invoker(Command command){
this.command = command;
}
/**
* 行动方法
*/
public void action(){
command.execute();
}
}
(5)接收者(Receiver)角色:
public class Receiver {
/**
* 真正执行命令相应的操作
*/
public void action(){
System.out.println("执行操作");
}
}
AudioPlayer系统

(1)接收者角色,由录音机类扮演
public class AudioPlayer {
public void play(){
System.out.println("播放...");
}
public void rewind(){
System.out.println("倒带...");
}
public void stop(){
System.out.println("停止...");
}
}
(2)抽象命令角色类
public interface Command {
/**
* 执行方法
*/
public void execute();
}
(3)具体命令角色类
public class PlayCommand implements Command {
private AudioPlayer myAudio;
public PlayCommand(AudioPlayer audioPlayer){
myAudio = audioPlayer;
}
/**
* 执行方法
*/
@Override
public void execute() {
myAudio.play();
}
}
public class RewindCommand implements Command {
private AudioPlayer myAudio; public RewindCommand(AudioPlayer audioPlayer){
myAudio = audioPlayer;
}
@Override
public void execute() {
myAudio.rewind();
}
}
public class StopCommand implements Command {
private AudioPlayer myAudio;
public StopCommand(AudioPlayer audioPlayer){
myAudio = audioPlayer;
}
@Override
public void execute() {
myAudio.stop();
}
}
(4)请求者角色,由键盘类扮演
public class Keypad {
private Command playCommand;
private Command rewindCommand;
private Command stopCommand;
public void setPlayCommand(Command playCommand) {
this.playCommand = playCommand;
}
public void setRewindCommand(Command rewindCommand) {
this.rewindCommand = rewindCommand;
}
public void setStopCommand(Command stopCommand) {
this.stopCommand = stopCommand;
}
/**
* 执行播放方法
*/
public void play(){
playCommand.execute();
}
/**
* 执行倒带方法
*/
public void rewind(){
rewindCommand.execute();
}
/**
* 执行播放方法
*/
public void stop(){
stopCommand.execute();
}
}
(5)客户端角色,由茱丽小女孩扮演
public class Julia {
public static void main(String[]args){
//创建接收者对象
AudioPlayer audioPlayer = new AudioPlayer();
//创建命令对象
Command playCommand = new PlayCommand(audioPlayer);
Command rewindCommand = new RewindCommand(audioPlayer);
Command stopCommand = new StopCommand(audioPlayer);
//创建请求者对象
Keypad keypad = new Keypad();
keypad.setPlayCommand(playCommand);
keypad.setRewindCommand(rewindCommand);
keypad.setStopCommand(stopCommand);
//测试
keypad.play();
keypad.rewind();
keypad.stop();
keypad.play();
keypad.stop();
}
}

5.优缺点:
(1)命令模式的优点:
(2)命令模式的缺点:
6.宏命令

(1)系统需要一个代表宏命令的接口,以定义出具体宏命令所需要的接口。
public interface MacroCommand extends Command {
/**
* 宏命令聚集的管理方法
* 可以添加一个成员命令
*/
public void add(Command cmd);
/**
* 宏命令聚集的管理方法
* 可以删除一个成员命令
*/
public void remove(Command cmd);
}
(2)具体的宏命令MacroAudioCommand类负责把个别的命令合成宏命令。
public class MacroAudioCommand implements MacroCommand {
private List<Command> commandList = new ArrayList<Command>();
/**
* 宏命令聚集管理方法
*/
@Override
public void add(Command cmd) {
commandList.add(cmd);
}
/**
* 宏命令聚集管理方法
*/
@Override
public void remove(Command cmd) {
commandList.remove(cmd);
}
/**
* 执行方法
*/
@Override
public void execute() {
for(Command cmd : commandList){
cmd.execute();
}
}
}
(3)客户端类Julia
public class Julia {
public static void main(String[]args){
//创建接收者对象
AudioPlayer audioPlayer = new AudioPlayer();
//创建命令对象
Command playCommand = new PlayCommand(audioPlayer);
Command rewindCommand = new RewindCommand(audioPlayer);
Command stopCommand = new StopCommand(audioPlayer);
MacroCommand marco = new MacroAudioCommand();
marco.add(playCommand);
marco.add(rewindCommand);
marco.add(stopCommand);
marco.execute();
}
}

7.撤销命令
/**
* 包含撤销命令的接口
* @author
*/
public interface Command {
//执行方法
void execute();
//撤销方法
void undo();
}
/**
* 具体命令 -- 创建目录
* @author
*/
public class CreateDirCommand implements Command {
private String dirName;
MakeDir makeDir;
public CreateDirCommand(MakeDir makeDir,String dirName) {
this.makeDir = makeDir;
this.dirName = dirName;
}
@Override
public void execute() {
makeDir.createDir(dirName);
} @Override
public void undo() {
makeDir.deleteDir(dirName);
}
}
/**
* 命令接受者
* 包含两个命令:创建目录、删除目录
* @author
*/
public class MakeDir {
//创建目录
public void createDir(String name){
File dir = new File(name);
if (dir.exists()) {
System.out.println("创建目录 " + name + " 失败,目标目录已经存在");
}else{
//创建目录
if (dir.mkdirs()) {
System.out.println("创建目录 " + name + " 成功");
} else {
System.out.println("创建目录 " + name + " 失败");
}
}
}
//删除目录
public void deleteDir(String name){
File dir = new File(name);
if(dir.exists()) {
if(dir.delete()){
System.out.println("删除目录 " + name + " 成功");
}else{
System.out.println("删除目录 " + name + " 失败");
}
}else{
System.out.println("删除目录 " + name + " 失败,目标目录不存在");
}
}
}
/**
* 请求者
* @author
*/
public class RequestMakeDir {
Command createCommand;
public void setCreateCommand(Command command) {
this.createCommand = command;
}
public void executeCreateCommand(){
createCommand.execute();
}
public void undoCreateCommand(){
createCommand.undo();
}
}
/**
* 测试
* @author
*/
public class Client {
public static void main(String[] args) {
String dir = "E:\\command2017"; //创建接收者
MakeDir makeDir = new MakeDir();
//创建具体命令并且指定接收者
Command create_command = new CreateDirCommand(makeDir,dir);
//创建请求者
RequestMakeDir request = new RequestMakeDir();
//设置命令
request.setCreateCommand(create_command);
/***********创建目录及撤销**************/
//创建目录
request.executeCreateCommand();
//撤销
request.undoCreateCommand();
}
}
创建目录 E:\command2017 成功
删除目录 E:\command2017 成功
8.多次撤销
/**
* 包含撤销命令的接口
* @author
*/
public interface Command {
//执行方法
void execute(String dirName);
//撤销方法
void undo();
}
/**
* 具体命令 -- 创建目录
* @author
*/
public class CreateDirCommand implements Command {
private ArrayList<String> dirNameList; //记录 这里用list实现
private MakeDir makeDir;
public CreateDirCommand(MakeDir makeDir) {
dirNameList = new ArrayList<String>();
this.makeDir = makeDir;
} @Override
public void execute(String dirName) {
makeDir.createDir(dirName);
dirNameList.add(dirName);
} @Override
public void undo() {
if(dirNameList.size()>0){
makeDir.deleteDir(dirNameList.get(dirNameList.size()-1));
dirNameList.remove(dirNameList.size()-1);
}else{
System.out.println("没有需要撤销的操作!");
}
}
}
/**
* 命令接受者
* 包含两个命令:创建目录、删除目录
* @author
*/
public class MakeDir {
//创建目录
public void createDir(String name){
File dir = new File(name);
if (dir.exists()) {
System.out.println("创建目录 " + name + " 失败,目标目录已经存在");
}else{
//创建目录
if (dir.mkdirs()) {
System.out.println("创建目录 " + name + " 成功");
} else {
System.out.println("创建目录 " + name + " 失败");
}
}
}
//删除目录
public void deleteDir(String name){
File dir = new File(name);
if(dir.exists()) {
if(dir.delete()){
System.out.println("删除目录 " + name + " 成功");
}else{
System.out.println("删除目录 " + name + " 失败");
}
}else{
System.out.println("删除目录 " + name + " 失败,目标目录不存在");
}
}
}
/**
* 请求者
* @author
*/
public class RequestMakeDir {
Command createCommand;
public void setCreateCommand(Command command) {
this.createCommand = command;
}
public void executeCreateCommand(String dirName){
createCommand.execute(dirName);
}
public void undoCreateCommand(){
createCommand.undo();
}
}
/**
* 测试
* @author
*/
public class Client {
public static void main(String[] args) {
//创建接收者
MakeDir makeDir = new MakeDir();
//创建具体命令并且指定接收者
Command create_command = new CreateDirCommand(makeDir);
//创建请求者
RequestMakeDir request = new RequestMakeDir();
//设置命令
request.setCreateCommand(create_command);
/***********创建目录及撤销**************/
//创建目录
request.executeCreateCommand("E:\\command\\2017");
request.executeCreateCommand("E:\\command\\2018");
request.executeCreateCommand("E:\\command\\2019");
request.executeCreateCommand("E:\\command\\2020");
//多次撤销
request.undoCreateCommand();
request.undoCreateCommand();
request.undoCreateCommand();
request.undoCreateCommand();
request.undoCreateCommand();
}
}
创建目录 E:\command\2017 成功
创建目录 E:\command\2018 成功
创建目录 E:\command\2019 成功
创建目录 E:\command\2020 成功
删除目录 E:\command\2020 成功
删除目录 E:\command\2019 成功
删除目录 E:\command\2018 成功
删除目录 E:\command\2017 成功
没有需要撤销的操作!
9.命令队列
/**
* 抽象命令角色类
* @author
*/
public interface Command {
/**
* 执行方法
*/
void execute();
}
/**
* 接收者角色类 - Java工程师
* @author
*/
public class JavaCoder {
/**
* 真正执行命令相应的操作
*/
public void work(String task){
System.out.println("java工程师要完成【"+task+"】");
}
}
/**
* 接收者角色类 - H5工程师
* @author
*/
public class H5Coder {
/**
* 真正执行命令相应的操作
*/
public void work(String task){
System.out.println("H5工程师要完成【"+task+"】");
}
}
/**
* 具体命令 -- Java工程师执行任务
* @author
*/
public class JavaCommand implements Command{
//持有相应的接收者对象
private JavaCoder javaCoder;
//具体任务
private String task;
/**
* 构造方法
*/
public JavaCommand(JavaCoder javaCoder,String task){
this.javaCoder = javaCoder;
this.task = task;
} @Override
public void execute() {
//通常会转调接收者对象的相应方法,让接收者来真正执行功能
javaCoder.work(this.task);
}
}
/**
* 具体命令 -- H5工程师执行任务
* @author
*/
public class H5Command implements Command{
//持有相应的接收者对象
private H5Coder h5Coder;
//具体任务
private String task;
/**
* 构造方法
*/
public H5Command(H5Coder h5Coder,String task){
this.h5Coder = h5Coder;
this.task = task;
} @Override
public void execute() {
//通常会转调接收者对象的相应方法,让接收者来真正执行功能
h5Coder.work(this.task);
}
}
/**
* CommandQueue命令队列类
* @author
*/
public class CommandQueue {
//定义一个ArrayList来存储命令队列
private ArrayList<Command> commands = new ArrayList<Command>(); public void addCommand(Command command) {
commands.add(command);
} public void removeCommand(Command command) {
commands.remove(command);
} //循环调用每一个命令对象的execute()方法
public void execute() {
for(Command command : commands) {
command.execute();
}
}
}
/**
* 请求发送者类Manager针对CommandQueue编程
* @author
*/
public class Manager {
private CommandQueue commandQueue; //维持一个CommandQueue对象的引用 //构造注入
public Manager(CommandQueue commandQueue) {
this. commandQueue = commandQueue;
} //设值注入
public void setCommandQueue(CommandQueue commandQueue) {
this.commandQueue = commandQueue;
} //调用CommandQueue类的execute()方法
public void call() {
commandQueue.execute();
}
}
测试:
/**
*
* @author
*/
public class Client {
public static void main(String[] args) {
//创建接收者
JavaCoder javaCoder = new JavaCoder();
H5Coder h5Coder = new H5Coder();
//创建命令对象
JavaCommand javaCommand = new JavaCommand(javaCoder,"登录模块的后台代码");
H5Command h5Command = new H5Command(h5Coder,"登录模块的前台代码");
//创建命令对象队列
CommandQueue commandqueue = new CommandQueue();
commandqueue.addCommand(javaCommand);
commandqueue.addCommand(h5Command);
//创建请求者,把命令对象设置进去
Manager manager = new Manager(commandqueue);
//执行方法
manager.call();
}
}
java工程师要完成【登录模块的后台代码】
H5工程师要完成【登录模块的前台代码】
10.请求日志
/**
* 抽象命令类,由于需要将命令对象写入文件,因此它实现了Serializable接口
* @author
*/
public abstract class Command implements Serializable {
private static final long serialVersionUID = 1L; protected String name; //命令名称
protected String args; //命令参数
protected Operator operator; //接收者对象
public Command(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public void setOperator(Operator operator) {
this.operator = operator;
}
//声明两个抽象的执行方法execute()
public abstract void execute(String args);
public abstract void execute();
}
/**
* 请求接收者 -- 由于Operator类的对象是Command的成员对象,它也将随Command对象一起写入文件,因此Operator也需要实现Serializable接口
* @author
*/
public class Operator implements Serializable{
private static final long serialVersionUID = 1L; public void insert(String args) {
System.out.println("新增数据:" + args);
} public void update(String args) {
System.out.println("修改数据:" + args);
} public void delete(String args) {
System.out.println("删除数据:" + args);
}
}
/**
* 具体命令角色类 -- 插入命令
* @author
*/
public class InsertCommand extends Command{
public InsertCommand(String name) {
super(name);
} public void execute(String args) {
this.args = args;
operator.insert(args);
} public void execute() {
operator.insert(this.args);
}
}
/**
* 具体命令角色类 -- 修改命令
* @author
*/
public class UpdateCommand extends Command{
public UpdateCommand(String name) {
super(name);
} public void execute(String args) {
this.args = args;
operator.update(args);
} public void execute() {
operator.update(this.args);
}
}
/**
* 具体命令角色类 -- 删除命令
* @author
*/
public class DeleteCommand extends Command{
public DeleteCommand(String name) {
super(name);
} public void execute(String args) {
this.args = args;
operator.delete(args);
} public void execute() {
operator.delete(this.args);
}
}
import com.designpattern.utils.FileUtil;
/**
* 请求发送者
* @author
*/
public class SqlExecuteTool {
//定义一个集合来存储每一次操作时的命令对象
private ArrayList<Command> commands = new ArrayList<Command>();
private Command command; //注入具体命令对象
public void setCommand(Command command) {
this.command = command;
} //执行配置文件修改命令,同时将命令对象添加到命令集合中
public void call(String args) {
command.execute(args);
commands.add(command);
} //记录请求日志,生成日志文件,将命令集合写入日志文件
public void save() {
FileUtil.writeCommands(commands);
} //从日志文件中提取命令集合,并循环调用每一个命令对象的execute()方法来实现配置文件的重新设置
public void recover() {
ArrayList list = FileUtil.readCommands();
for (Object obj : list) {
((Command)obj).execute();
}
}
}
package com.designpattern.Command.extend.RequestLog;
/**
* 测试
* @author
*/
public class Client {
public static void main(String[] args) {
SqlExecuteTool tool = new SqlExecuteTool(); //定义请求发送者
Operator operator = new Operator(); //定义请求接收者 Command command; //执行了很多次SQL
command = new InsertCommand("增加");
command.setOperator(operator);
tool.setCommand(command);
tool.call("insert xxx"); command = new InsertCommand("增加");
command.setOperator(operator);
tool.setCommand(command);
tool.call("insert xxx"); command = new UpdateCommand("修改");
command.setOperator(operator);
tool.setCommand(command);
tool.call("update xxx"); command = new DeleteCommand("删除");
command.setOperator(operator);
tool.setCommand(command);
tool.call("delete xxx"); System.out.println("-------------------------------------");
System.out.println("保存执行的sql");
tool.save();
System.out.println("-------------------------------------");
System.out.println("恢复执行的sql");
System.out.println("-------------------------------------");
tool.recover();
}
}
新增数据:insert xxx
新增数据:insert xxx
修改数据:update xxx
删除数据:delete xxx
-------------------------------------
保存执行的sql
-------------------------------------
恢复执行的sql
-------------------------------------
新增数据:insert xxx
新增数据:insert xxx
修改数据:update xxx
删除数据:delete xxx
设计模式(14)--Command(命令模式)--行为型的更多相关文章
- 设计模式(十四):Command命令模式 -- 行为型模式
1.概述 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来 ...
- 设计模式14:Command 命令模式(行为型模式)
Command 命令模式(行为型模式) 耦合与变化 耦合是软件不能抵御变化的根本性原因.不仅实体对象与实体对象之间存在耦合关系,实体对象与行为操作之间也存在耦合关系. 动机(Motivation) 在 ...
- 第14章 命令模式(Command Pattern)
原文 第14章 命令模式(Command Pattern) 命令模式(Command Pattern) 概述 在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”.但在某些场合,比如 ...
- 设计模式之第14章-命令模式(Java实现)
设计模式之第14章-命令模式(Java实现) “小明,滚出去.”“小明,这个问题怎么做?”(可怜的小明无奈躺枪.小明:老师,我和你有什么仇什么怨,我和你有什么仇什么怨啊到底...老师:小明,滚出去.习 ...
- C++设计模式-Command命令模式
Command命令模式作用:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 由于“行为请求者”与“行为实现者”的紧耦合,使用命令模式 ...
- 22、Command 命令模式
1.command 命令模式 命令模式(Command Pattern):在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指 ...
- 设计模式学习之命令模式(Command,行为型模式)(12)
一.命令模式的定义 命令模式属于对象的行为型模式.命令模式是把一个操作或者行为抽象为一个对象中,通过对命令的抽象化来使得发出命令的责任和执行命令的责任分隔开.命令模式的实现可以提供命令的撤销和恢复功能 ...
- c#设计模式系列:命令模式(Command Pattern)
引言 命令模式,我感觉"命令"就是任务,执行了命令就完成了一个任务.或者说,命令是任务,我们再从这个名字上并不知道命令的发出者和接受者分别是谁,为什么呢?因为我们并不关心他们是谁, ...
- C#设计模式系列:命令模式(Command)
1.命令模式简介 1.1>.定义 命令模式的目的是解除命令发出者和接收者之间的紧密耦合关系,使二者相对独立,有利于程序的并行开发和代码的维护.命令模式的核心思想是将请求封装为一个对象,将其作为命 ...
随机推荐
- 网页关闭(解决window.close在火狐下不兼容问题)
熟悉前端的都知道,火狐默认状态非window.open的页面window.close是无效的 网上有很多人说,在火狐的地址栏输入:about:config然后找到dom.allow_scripts_t ...
- Swfit 里 Array(五)和 NSArray 转换
 只看 Swift Array 到 NSArray Array 里的源代码 extension Array { @inlinable public // @SPI(Foundation) func ...
- python实用库:PrettyTable 学习
python实用库:PrettyTable 学习 PrettyTable说明 PrettyTable 是python中的一个第三方库,可用来生成美观的ASCII格式的表格,十分实用. 以下为官方介绍: ...
- Redis学习系列二之.Net开发环境搭建及基础数据结构String字符串
一.简介 Redis有5种基本数据结构,分别是string.list(列表).hash(字典).set(集合).zset(有序集合),这是必须掌握的5种基本数据结构.注意Redis作为一个键值对缓存系 ...
- Vue.js之组件(component)
从结构上看,组件之于实例,就好比轮子之于汽车.从属性和方法来看,组件有实例的大部分方法,如果Vue实例是孙悟空,组件就好比实例的一个毫毛,变化多端却为Vue实例所用. 目录: 组件的注册 is的作用 ...
- 遍历 JSON JavaScript 对象树中的所有节点
我想要遍历 JSON 对象树中,但为何找不到任何一间图书馆.这似乎是不难,但感觉就像重新发明轮子. 在 XML 中有很多教程演示如何遍历 XML DOM 树:( 解决方法 1: 如果你认为 jQuer ...
- Selenium3自动化问题二:各chrome版本对应的chromedriver版本
一:问题说明 最近用到selenium3在火狐浏览器中执行自动化脚本,遇到了一些问题,最后解决方案中占比最多的就是浏览器和驱动版本不一致导致的,故这里给出chrome.firefox驱动的不同版本对应 ...
- linux wheel组
wheel 组的概念 wheel 组的概念继承自 UNIX.当服务器需要进行一些日常系统管理员无法执行的高级维护时,往往就要用到 root 权限:而“wheel” 组就是一个包含这些特殊权限的用户池: ...
- 让 markdown 生成带目录的 html 文件
安装 npm install -g i5ting_toc 用法 进入 markdown 文件所在的文件夹 举个栗子: 你的sample.md文件放在桌面上 cd /Users/dora/Desktop ...
- 【Leetcode】338. Bit位计数
每次刷leetcode都有一种发现新大陆的感觉. 题目链接:https://leetcode-cn.com/problems/counting-bits/description/ 给定一个非负整数 n ...