设计模式(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>.定义 命令模式的目的是解除命令发出者和接收者之间的紧密耦合关系,使二者相对独立,有利于程序的并行开发和代码的维护.命令模式的核心思想是将请求封装为一个对象,将其作为命 ...
随机推荐
- JS获取浏览器URL中查询字符串的参数
首先要知道Location这个对象以及这个对象中的一些属性: href:设置或返回完整的url.如本博客首页返回http://www.cnblogs.com/wymninja/ host:设置或返回主 ...
- python之ETL数据清洗案例源代码
#python语言 import pandas as pd import time data = pd.read_excel('ETL_数据清洗挑战.xlsx','测试数据',dtype=str)#读 ...
- docker 下安装mssql-server-linux
docker search mssql 查找mssql镜像 docker pull microsoft/mssql-server-linux 拉去mssql镜像 docker images 查看镜像 ...
- 01-Linux的基本指令
Linux的基本指令 基础指令(重点) 1.ls指令: 含义:ls(list) 用法1:#ls 含义:列出当前工作目录下的所有文件/文件夹的名称 用法2:#ls 路径 含义:列出指定路径下的所有文件 ...
- 使用IST重新加入节点(5.7.20)
IST不是SST用于节点重新加入吗?我们有解决方案! 鉴于上述痛点,我们将介绍 gcache.freeze_purge_at_seqno Percona XtraDB Cluster 5.7.20.这 ...
- OS之内存管理 --- 虚拟内存管理(一)
虚拟内存的背景 在基本的内存管理策略中,所有的策略的相同点都是:每个进程在执行之前需要完全处于内存中.那有没有一种方法可以不需要将进程所有页面加载到内存中就可以开始运行进程呢?有没有可能在进程需要某些 ...
- List集合和Set集合的遍历方法
Set集合遍历方法: 对 set 的遍历 1.迭代遍历: Set<String> set = new HashSet<String>(); Iterator<String ...
- storm_分组策略
注意1:原始的案例 spout 和bolt都是1个并发 所以文件中30条日志 从spout发出以后 bolt接受到30条
- 通俗易懂详解Java代理及代码实战
一.概述 代理模式是Java常用的设计模式之一,实现代理模式要求代理类和委托类(被代理的类)具有相同的方法(提供相同的服务),代理类对象自身并不实现真正的核心逻辑,而是通过调用委托类对象的相关方法来处 ...
- [java初探06]__排序算法的简单认识
今天,准备填完昨天没填的坑,将排序算法方面的知识系统的学习一下,但是在简单的了解了一下后,有些不知如何组织学习了,因为排序算法的种类,实在是太多了,各有优略,各有适用的场景.有些不知所措,从何开始. ...