1,简单命令模式:
对命令的发出者和接受者实现解耦
Command 命令接口,定义execute方法
ConcreteCommand 命令实现类,执行execute方式调用Receiver执行action方法
Receiver命令接受者,执行方法为action
Invoker命令发布者:持有Command接口
抽象命令角色类
public interface Command {
/**
* 执行方法
*/
void execute();
}
具体命令角色类
public class ConcreteCommand implements Command {
//持有相应的接收者对象
private Receiver receiver = null;
/**
* 构造方法
*/
public ConcreteCommand(Receiver receiver){
this.receiver = receiver;
}
@Override
public void execute() {
//通常会转调接收者对象的相应方法,让接收者来真正执行功能
receiver.action();
}
}
接收者角色类
public class Receiver {
/**
* 真正执行命令相应的操作
*/
public void action(){
System.out.println("执行操作");
}
}
请求者角色类
public class Invoker {
/**
* 持有命令对象
*/
private Command command = null;
/**
* 构造方法
*/
public Invoker(Command command){
this.command = command;
}
/**
* 行动方法
*/
public void action(){
command.execute();
}
}
客户端角色类
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,宏命令模式
概念:宏命令就是一系列命令
通过invoker执行时调用一系列command命令
package com.designpattern.Command.extend.MacroCommand;
import java.util.ArrayList;
/**
* 宏命令接口实现
* @author huffman
*/
public class ComputerMacroCommand implements MacroCommand {
private ArrayList<Command> commands;
//无参构造方法
public ComputerMacroCommand(){
commands = new ArrayList<Command>();
}
@Override
public void addCommand(Command command){
commands.add(command);
}
@Override
public void removeCommand(Command command){
commands.remove(command);
}
@Override
public void execute(){
for (int i=0; i < commands.size(); i++){
commands.get(i).execute();
}
}
}
设置一个computer(命令执行者)可以执行开机的一系列动作
package com.designpattern.Command.extend.MacroCommand;
/**
* 接收者角色类
* @author huffman
*/
public class Computer {
public void startBIOS(){
System.out.println("BIOS启动...");
}
public void startMBR(){
System.out.println("MBR加载...");
}
public void startHDD(){
System.out.println("HDD加载...");
}
public void startOS(){
System.out.println("系统启动...");
}
然后执行用command的实现类分别调用computer对象并实现某一个功能
package com.designpattern.Command.extend.MacroCommand;
/**
* 具体命令 -- OS启动命令
* @author huffman
*/
public class OSStartCommand implements Command {
private Computer computer;
public OSStartCommand(Computer computer){
this.computer = computer;
}
@Override
public void execute() {
computer.startOS();
}
}
package com.designpattern.Command.extend.MacroCommand;
/**
* 具体命令 -- HDD启动命令
* @author huffman
*/
public class HDDStartCommand implements Command {
private Computer computer;
public HDDStartCommand(Computer computer){
this.computer = computer;
}
@Override
public void execute() {
computer.startHDD();
}
}
package com.designpattern.Command.extend.MacroCommand;
/**
* 具体命令 -- MBR启动命令
* @author huffman
*/
public class MBRStartCommand implements Command {
private Computer computer;
public MBRStartCommand(Computer computer){
this.computer = computer;
}
@Override
public void execute() {
computer.startMBR();
}
}
package com.designpattern.Command.extend.MacroCommand;
/**
* 具体命令 -- BIOS启动命令
* @author huffman
*/
public class BIOSStartCommand implements Command {
private Computer computer;
public BIOSStartCommand(Computer computer){
this.computer = computer;
}
@Override
public void execute() {
computer.startBIOS();
}
}
最后来看入口方法
package com.designpattern.Command.extend.MacroCommand;
/**
* 测试
* @author huffman
*/
public class Client {
public static void main(String[] args) {
//创建接收者
Computer computer = new Computer();
//创建命令对象,设定它的接收者
Command bios_command = new BIOSStartCommand(computer);
//创建命令对象,设定它的接收者
Command mbr_command = new MBRStartCommand(computer);
//创建命令对象,设定它的接收者
Command hdd_command = new HDDStartCommand(computer);
//创建命令对象,设定它的接收者
Command os_command = new OSStartCommand(computer);
//命令控制对象Invoker,把命令对象通过构造方法设置进去
MacroCommand invoker = new ComputerMacroCommand();
invoker.addCommand(bios_command);
invoker.addCommand(mbr_command);
invoker.addCommand(hdd_command);
invoker.addCommand(os_command);
System.out.println("我要是用电脑,于是按下开机按钮...");
invoker.execute();
System.out.println("现在可以使用电脑了!!!");
}
}
3,撤销命令模式
命令带执行和撤销(回退)
原理:command接口多一个undo方法,命令执行者执行撤销命令时调用undo方法;同时command的实现类也同时实现(execute和undo)传入同一个命令执行者
package com.designpattern.Command.extend.Undo;
/**
* 包含撤销命令的接口
* @author huffman
*/
public interface Command {
//执行方法
void execute();
//撤销方法
void undo();
}
package com.designpattern.Command.extend.Undo;
/**
* 具体命令 -- 创建目录
* @author Json
*/
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);
}
}
package com.designpattern.Command.extend.Undo;
import java.io.File;
/**
* 命令接受者
* 包含两个命令:创建目录、删除目录
* @author Json
*/
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 + " 失败,目标目录不存在");
}
}
}
package com.designpattern.Command.extend.Undo;
/**
* 请求者
* @author huffman
*/
public class Invoker {
Command createCommand;
public void setCreateCommand(Command command) {
this.createCommand = command;
}
public void executeCreateCommand(){
createCommand.execute();
}
public void undoCreateCommand(){
createCommand.undo();
}
}
package com.designpattern.Command.extend.Undo;
/**
* 测试
* @author huffman
*/
public class Client {
public static void main(String[] args) {
String dir = "E:\\command2017";
//创建接收者
MakeDir makeDir = new MakeDir();
//创建具体命令并且指定接收者
Command create_command = new CreateDirCommand(makeDir,dir);
//创建请求者
Invoker request = new Invoker();
//设置命令
request.setCreateCommand(create_command);
/***********创建目录及撤销**************/
//创建目录
request.executeCreateCommand();
//撤销
request.undoCreateCommand();
}
}
4,命令模式扩展-命令队列
把1,命令模式和2,宏命令的功能合起来,做一个命令队列
public class Invoker {
private CommandQueue commandQueue; //维持一个CommandQueue对象的引用
//构造注入
public Invoker(CommandQueue commandQueue) {
this. commandQueue = commandQueue;
}
//设值注入
public void setCommandQueue(CommandQueue commandQueue) {
this.commandQueue = commandQueue;
}
//调用CommandQueue类的execute()方法
public void call() {
commandQueue.execute();
}
}
package com.designpattern.Command.extend.CommandQueue;
import java.util.ArrayList;
/**
* CommandQueue命令队列类
* @author Json
*/
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();
}
}
}
package com.designpattern.Command.extend.CommandQueue;
/**
* 接收者角色类 - Java工程师
* @author huffman
*/
public class JavaReceiver implements Receiver{
/**
* 真正执行命令相应的操作
*/
public void work(String task){
System.out.println("java工程师要完成【"+task+"】");
}
}
package com.designpattern.Command.extend.CommandQueue;
/**
* 接收者角色类 - Java工程师
* @author huffman
*/
public class H5Receiver implements Receiver{
/**
* 真正执行命令相应的操作
*/
public void work(String task){
System.out.println("H5工程师要完成【"+task+"】");
}
}
package com.designpattern.Command.extend.CommandQueue;
/**
* 具体命令 -- Java工程师执行任务
* @author huffman
*/
public class Command implements Command{
//持有相应的接收者对象
private Receiver receiver;
//具体任务
private String task;
/**
* 构造方法
*/
public JavaCommand(JavaReceiver javaCoder,String task){
this.javaCoder = javaCoder;
this.task = task;
}
@Override
public void execute() {
//通常会转调接收者对象的相应方法,让接收者来真正执行功能
javaCoder.work(this.task);
}
}
package com.designpattern.Command.extend.CommandQueue;
/**
*
* @author Json
*/
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();
}
}
package com.designpattern.Command.extend.CommandQueue;
/**
*
* @author Json
*/
public class Client {
public static void main(String[] args) {
//创建接收者
JavaReceiver javaCoder = new JavaReceiver ();
H5Receiver h5Coder = new H5Receiver();
//创建命令对象
JavaCommand javaCommand = new JavaCommand(javaCoder,"登录模块的后台代码");
H5Command h5Command = new H5Command(h5Coder,"登录模块的前台代码");
//创建命令对象队列
CommandQueue commandqueue = new CommandQueue();
commandqueue.addCommand(javaCommand);
commandqueue.addCommand(h5Command);
//创建请求者,把命令对象设置进去
Invoker manager = new Invoker(commandqueue);
//执行方法
manager.call();
5,命令模式扩展-请求日志
操作数据库时,需要记录操作的请求日志,便于做恢复和回退
或者是分布式事务做控制,如果其中有一步异常就做回退,也可以用这种方式
指定一个唯一的命令发送者Tool和命令接受者Receiver
然后命令发送者能够发送一系列指令(Command),同时具有保存提交执行(commit)或者回退(Recover)指令的功能
Command执行其实是调用Receiver的功能,但是Receiver对Tool命令发送者不可见
package com.designpattern.Command.extend.RequestLog;
import java.util.ArrayList;
import com.designpattern.utils.FileUtil;
/**
* 请求发送者
* @author Json
*/
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 (int i=list.length-1;i>=0;i--) {
((Command)list.get(i)).execute();
}
}
}
package com.designpattern.Command.extend.RequestLog;
import java.io.Serializable;
/**
* 抽象命令类,由于需要将命令对象写入文件,因此它实现了Serializable接口
* @author Json
*/
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();
}
package com.designpattern.Command.extend.RequestLog;
import java.io.Serializable;
/**
* 请求接收者 -- 由于Operator类的对象是Command的成员对象,它也将随Command对象一起写入文件,因此Operator也需要实现Serializable接口
* @author Json
*/
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);
}
}
package com.designpattern.Command.extend.RequestLog;
/**
* 具体命令角色类 -- 插入命令
* @author Json
*/
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);
}
}
package com.designpattern.Command.extend.RequestLog;
/**
* 测试
* @author Json
*/
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();
}
}
打完收工!