行为型模式之Command模式

命令模式将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,

并且可以对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

概念描述

把命令的调用者与执行者分开,使双方不必关心对方是如何操作的。
比如有一组文件操作的命令:新建文件、复制文件、删除文件。如果把这三个操作都封装成一个命令类,客户端只需要知道有这三个命令类即可,至于命令类中封装好的逻辑,客户端则无需知道。

在JDK中的体现

允许子类重载部分父类而不需要完全重写。
* java.util.Collections#sort()
* java.io.InputStream#skip()
* java.io.InputStream#read()
* java.util.AbstractList#indexOf()


参与角色

Command类:是一个抽象类,类中对需要执行的命令进行声明,一般来说要对外公布一个execute方法用来执行命令。
ConcreteCommand类:Command类的实现类,对抽象类中声明的方法进行实现。
Client类:最终的客户端调用类。
Invoker类:调用者,负责调用命令。
Receiver类:接收者,负责接收命令并且执行命令。

命令模式实例

当我们调用时,执行的时序首先是调用者类,然后是命令类,最后是接收者类。
一条命令的执行被分成了三步,耦合度要比把所有的操作都封装到一个类中要低的多。

public abstract class Command {
	
	public abstract void execute();

}

/**
 * 具体命令的实现类
 * @author bingyue56@163.com 
 */
public class ConcreteCommand extends Command{
	
	private Receiver receiver;
	
	public ConcreteCommand(Receiver receiver){
		this.receiver=receiver;
	}

	/**
	 * 具体的调用通过命令接收者来实现
	 */
	@Override
	public void execute() {
		this.receiver.action();
	}
}
public class Receiver {

	/**
	 * 真正执行命令操作的代码
	 */
	public void action(){
		System.out.println("命令接收者-执行具体业务逻辑");
	}
}

  

/**
 * 调用者 负责调用命令
 */
public class Invoker {

	private Command command;  
	
    public void setCommand(Command command) {  
        this.command = command;  
    }  
    public void action(){  
        this.command.execute();  
    }  
}

  

/**
 * 客户端调用
 * @author bingyue56@163.com 
 */
public class Client {

	public static void main(String[] args){
		//得到业务逻辑执行者
		Receiver receiver=new Receiver();
		//命令类-注入具体业务逻辑接收者
		Command command =new ConcreteCommand(receiver);
		/**
		 * 两种调用方式
		 * 1.命令类直接调用执行
		 */
		command.execute();
		/**
		 * 2.通过invoker的方式注入命令
		 */
		Invoker invoker=new Invoker();
		invoker.setCommand(command);
		//调用内部command的执行
		invoker.action();
	}
	
}

适用场景

1.使用命令模式作为"CallBack"在面向对象系统中的替代。CallBack讲的便是先将一个函数登记上,然后在以后调用此函数。

2.需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接收者可以是在本地,也可以在网络的另外一个地址。命令对象可以在序列化之后传送到另外一台机器上去。

3.系统需要支持命令的撤消(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo()方法,把命令所产生的效果撤销掉。命令对象还可以提供redo()方法,以供客户端在需要时,再重新实施命令效果。

4.如果一个系统要将系统中所有的数据更新到日志里,以便在系统崩溃时,可以根据日志里读回所有的数据更新命令,重新调用Execute()方法一条一条执行这些命令,从而恢复系统在崩溃前所做的数据更新。

参考整理自:

Java之命令模式(Command Pattern)

23种设计模式(10):命令模式   

原文地址:https://www.cnblogs.com/binyue/p/4516498.html