命令模式
类型:行为型
将一个请求封装为一个对象,从而使你可用不同的请求对象对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
角色
- Receive接收者角色,处理命令
- Command命令角色,需要执行的请求
- Invoker调用者角色,接收命令,并执行命令
UML
包结构
receiver
package 命令模式.receiver;
public class TV {
public void playCCTV1() {
System.out.println("--CCTV1--");
}
public void playCCTV2() {
System.out.println("--CCTV2--");
}
public void playCCTV3() {
System.out.println("--CCTV3--");
}
}
command
父类
package 命令模式.command;
import 命令模式.receiver.TV;
public abstract class Command {
protected TV tv;
public Command(TV tv){
this.tv=tv;
}
public abstract void excute();
}
子类
package 命令模式.command;
import 命令模式.receiver.TV;
public class CCTV1Command extends Command{
public CCTV1Command(TV tv) {
super(tv);
}
@Override
public void excute() {
super.tv.playCCTV1();
}
}
---------------------------------------------
package 命令模式.command;
import 命令模式.receiver.TV;
public class CCTV2Command extends Command{
public CCTV2Command(TV tv) {
super(tv);
}
@Override
public void excute() {
super.tv.playCCTV2();
}
}
---------------------------------------------
package 命令模式.command;
import 命令模式.receiver.TV;
public class CCTV3Command extends Command{
public CCTV3Command(TV tv) {
super(tv);
}
@Override
public void excute() {
super.tv.playCCTV3();
}
}
---------------------------------------------
invoker
package 命令模式.invoker;
import 命令模式.command.Command;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class TVController {
//创建存储历史命令记录的数组
List<Command> historyRecord = new ArrayList<>();
public void inputCommand(Command command){
historyRecord.add(command);
command.excute();
}
public void undo(){
if(historyRecord.isEmpty()){
System.out.println("频道为空,不能执行撤回操作");
return;
}
if(historyRecord.size()==1){
System.out.println("已经是第一个操作了,不能再撤回了");
return;
}
historyRecord.remove(historyRecord.size()-1);
historyRecord.get(historyRecord.size()-1).excute();
}
}
client
package 命令模式.client;
import 命令模式.command.CCTV1Command;
import 命令模式.command.CCTV2Command;
import 命令模式.command.CCTV3Command;
import 命令模式.invoker.TVController;
import 命令模式.receiver.TV;
public class Client{
public static void main(String[] args) {
TV tv = new TV();
TVController tc = new TVController();
System.out.println("------切换频道中-----");
tc.inputCommand(new CCTV2Command(tv));
tc.inputCommand(new CCTV3Command(tv));
tc.inputCommand(new CCTV1Command(tv));
System.out.println("-------撤销操作-------");
tc.undo();
tc.undo();
tc.undo();
}
}
效果
------切换频道中-----
--CCTV2--
--CCTV3--
--CCTV1--
-------撤销操作-------
--CCTV3--
--CCTV2--
已经是第一个操作了,不能再撤回了
Process finished with exit code 0
优点
- 更松散的耦合,将发起命令的客户端与具体处理命令的接收者完全解耦,客户端完全不知道接收者是什么样子。
- 更动态的控制,把请求封装起来,可以动态的对请求进行参数化、队列化和日志化等,使系统更灵活。
- 复合命令,很容易地组合命令,即宏命令,使系统功能更强大。
- 更好的扩展,很容易添加新的命令。
缺点
类数量随命令数量增长而增长。可能造成类数量过多。(设计模式常见的缺点)