《命令模式》
命令模式:将一个请求封装成一个对象,从而使你可用不同的请求对客户端进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。将发出请求的对象与接收请求的对象分隔开来,松耦合。
玩网游的人都知道“宏命令”的概念,玩家可以编制自己的宏命令来节省操作,这里使用紧耦合的方式实现角色的一连串技能施法:
public class Wizard {
public void iceAttack(){
System.out.println("施法-寒冰箭");
}
public void fireballAttack(){
System.out.println("施法-火球术");
}
public static void main(String[] args) {
Wizard wizard = new Wizard();
//执行一连串的命令
wizard.iceAttack();
wizard.iceAttack();
wizard.iceAttack();
wizard.fireballAttack();
wizard.iceAttack();
wizard.iceAttack();
}
}
采用紧耦合的方式虽然非常简单,但是如果技能过多,命令过多时,就会乱套,也没办法记录顺序和有效的调整技能。
使用命令模式实现:
//命令调度者,持有命令对象的引用
public class Player {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
//执行命令的方法
public void confirm(){
command.execute();
}
//撤销命令
public void cancel(){
command.undo();
}
}
//抽象命令接口
public interface Command {
void execute();//执行命令方法
void undo();//撤销方法
}
//具体的命令,需要持有一个具体的命令接收者
public class IceCommand implements Command{
private Wizard receiver;
public IceCommand(Wizard receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.attack();
}
@Override
public void undo() {
receiver.cancel();
}
}
public class FireballCommand implements Command {
private Wizard receiver;
public FireballCommand(Wizard receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.attack();
}
@Override
public void undo() {
receiver.cancel();
}
}
//命令接收者接口
public interface Wizard {
void attack();
void cancel();
}
//具体的命令执行者
public class FireballWizard implements Wizard {
@Override
public void attack() {
System.out.println("施法-寒冰箭");
}
@Override
public void cancel() {
System.out.println("取消施法-寒冰箭");
}
}
public class IceWizard implements Wizard {
@Override
public void attack() {
System.out.println("施法-火球术");
}
@Override
public void cancel() {
System.out.println("取消施法-火球术");
}
}
//测试
public class CommandTest {
@Test
public void testCommand(){
//创建调用者
Player con = new Player();
//创建Command
IceCommand c1 = new IceCommand(new IceWizard());
//设置命令
con.setCommand(c1);
//执行命令
con.confirm();
//取消
con.cancel();
}
}
我们在扩展一下,实现宏命令的功能:
//宏命令,使用集合来保存所有需要执行的命令
public class MacroCommand implements Command {
private List<Command> commands;
public MacroCommand(List<Command> commands) {
this.commands = commands;
}
@Override
public void execute() {
for (Command command : commands) {
command.execute();
}
}
@Override
public void undo() {
for (Command command : commands) {
command.undo();
}
}
}
//测试
public class CommandTest {
@Test
public void testCommand(){
//创建调用者
Player con = new Player();
//创建Command
IceCommand ic1 = new IceCommand(new IceWizard());
IceCommand ic2 = new IceCommand(new IceWizard());
IceCommand ic3 = new IceCommand(new IceWizard());
IceCommand ic4 = new IceCommand(new IceWizard());
FireballCommand f1 = new FireballCommand(new FireballWizard());
FireballCommand f2 = new FireballCommand(new FireballWizard());
List<Command> commands = new ArrayList<>();
commands.add(ic1);
commands.add(ic2);
commands.add(f1);
commands.add(ic3);
commands.add(ic4);
commands.add(f2);
MacroCommand macroCommand = new MacroCommand(commands);
con.setCommand(macroCommand);
con.confirm();
}
}
总结:
命令模式在日志记录、队列请求、线程池等都能广泛的被应用。
命令模式的优点:
1.很容易实现命令队列
2.在需要的情况下可以将命令记入日志或者存储在物理磁盘中
3.可以实现命令的撤销
4.命令发起者和接收者完全解耦,即命令发起者并不知道具体的命令是什么以及执行命令的对象是什么,更易于扩展
5.通过不同的命令的组合实现宏命令