手写设计模式之命令模式

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(); 
    }
}

打完收工!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值