命令模式(将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理)
-
优点
1、降低了系统耦合度。
2、新的命令可以很容易添加到系统中去。 -
缺点
1、使用命令模式可能会导致某些系统有过多的具体命令类。 -
命令模式包含以下主要角色
抽象命令类角色:定义命令的接口,声明执行的方法。
具体命令类角色:具体命令实现类,拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
接收者角色:是真正执行命令的对象,执行命令功能的相关操作。
请求者角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。 -
例子:人用遥控板进行电视频道换台为例
抽象命令类角色
/**
* 换台命令接口
*/
public abstract class ChangeCommand {
public TV tv;
public ChangeCommand(TV tv) {
this.tv = tv;
}
public abstract void changeChannel();
}
具体命令类角色
/**
* 换到CCTV1频道命令
*/
public class ChangeCCTV1 extends ChangeCommand {
public ChangeCCTV1(TV tv) {
super(tv);
}
@Override
public void changeChannel() {
tv.changeCCTV1();
}
}
/**
* 换到CCTV2频道命令
*/
public class ChangeCCTV2 extends ChangeCommand {
public ChangeCCTV2(TV tv) {
super(tv);
}
@Override
public void changeChannel() {
tv.changeCCTV2();
}
}
/**
* 换到CCTV3频道命令
*/
public class ChangeCCTV3 extends ChangeCommand {
public ChangeCCTV3(TV tv) {
super(tv);
}
@Override
public void changeChannel() {
tv.changeCCTV3();
}
}
/**
* 换到CCTV4频道命令
*/
public class ChangeCCTV4 extends ChangeCommand {
public ChangeCCTV4(TV tv) {
super(tv);
}
@Override
public void changeChannel() {
tv.changeCCTV4();
}
}
接收者角色
/**
* 电视
*/
public class TV {
public void changeCCTV1() {
System.out.println("切换到CCTV1方法被调用...");
}
public void changeCCTV2() {
System.out.println("切换到CCTV2方法被调用...");
}
public void changeCCTV3() {
System.out.println("切换到CCTV3方法被调用...");
}
public void changeCCTV4() {
System.out.println("切换到CCTV4方法被调用...");
}
}
请求者角色
/**
* 人
*/
public class People {
private List<ChangeCommand> commandRecords = new ArrayList<>();
// 换台
public void change(ChangeCommand command) {
System.out.println("调用者执行换台命令...");
commandRecords.add(command);
command.changeChannel();
}
// 返回
public void back() {
System.out.println("调用者执行返回命令...");
// 当前历史小于2
if (commandRecords.size()< 2) {
return;
} else {
commandRecords.remove(commandRecords.size() - 1);
ChangeCommand upCommand = commandRecords.get(commandRecords.size() - 1);
upCommand.changeChannel();
}
}
}
测试
public class Test {
public static void main(String[] args) {
TV tv = new TV();
ChangeCommand cctv1 = new ChangeCCTV1(tv);
ChangeCommand cctv2 = new ChangeCCTV2(tv);
ChangeCommand cctv3 = new ChangeCCTV3(tv);
ChangeCommand cctv4 = new ChangeCCTV4(tv);
People people = new People();
people.change(cctv1);
people.change(cctv3);
people.change(cctv2);
people.change(cctv4);
people.back();
people.back();
people.back();
people.back();
}
}
// 运行结果
调用者执行换台命令...
切换到CCTV1方法被调用...
调用者执行换台命令...
切换到CCTV3方法被调用...
调用者执行换台命令...
切换到CCTV2方法被调用...
调用者执行换台命令...
切换到CCTV4方法被调用...
调用者执行返回命令...
切换到CCTV2方法被调用...
调用者执行返回命令...
切换到CCTV3方法被调用...
调用者执行返回命令...
切换到CCTV1方法被调用...
调用者执行返回命令...
命令模式就是将请求封装成一个个命令,以命令为参数来进行切换,达到请求参数化的目的,且还能通过集合这个数据结构来存储已经执行的请求,进行回退操作。如果需要添加新的电视频道,只需要添加新的命令类即可