命令模式(Command Pattern)——将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持科撤销的操作。
命令模式适用于“请求-响应”模式的功能,将用户的请求封装成对象(命令),用户需要执行什么样的操作,就调用什么样的命令,而无需知道命令的执行逻辑是什么。
命令模式主要包含以下几个概念:
1、Command:所有命令的抽象类,一般需要对外公开一个执行命令的方法execute,如有需要还需提供一个命令的撤销方法undo。
2、ConcreteCommand:命令的实现类。
3、Invoker:调用者,负责命令的调度。
4、Reveiver:接收者,负责命令的接收和执行。
5、Client:客户端,命令的发起者。
比如,一个有存取款功能的ATM机,它可以向某个银行的卡里存款,也可以从任何支持银联接口的银行卡里取款。不同的银行系统对存款、取款功能的实现均有不同,我们不关心银行怎么实现,只要点击ATM上的按钮就行了。这个例子中,银行的存款和取款分别为两个具体的命令实现类(ConcreteCommand);ATM机充当调用者(Invoker),负责调用银行存款或取款的命令;银行的系统为接收者(Reveiver),处理存款和取款的业务逻辑;使用ATM机的人就是客户端。
首先定义一个命令的抽象类,只有两个方法,执行和撤销:
public interface Command { public void execute(); public void undo(); }
模拟两个银行的系统,建行(CCB)和招行(CMB),简单一点,只有存款和取款的功能。为了模拟银行系统实现的差异,将存款、取款方法取成不同的名字。
建行:
public class Ccb { public void cunqian(long amount) { System.out.println("向建设银行存入金额:" + amount); } public void quqian(long amount) { System.out.println("从建设银行取出金额:" + amount); } }
招行:
public class Cmb{ public void saveMoney(long amount) { System.out.println("向招商银行存入金额:" + amount); } public void getMoney(long amount) { System.out.println("从招商银行取出金额:" + amount); } }
将银行的存款、取款动作封装成命令对象。为了避免太复杂,存款命令的撤销就当再取出来,取款命令的撤销就再存回去。
建行的存款命令:
public class CcbDepositCommand implements Command { private Ccb ccb = new Ccb(); @Override public void execute() { ccb.cunqian(100); } @Override public void undo() { ccb.quqian(100); } }
建行的取款命令:
public class CcbWithdrawCommand implements Command { private Ccb ccb = new Ccb(); @Override public void execute() { ccb.quqian(100); } @Override public void undo() { ccb.cunqian(100); } }
招行的存款命令:
public class CmbDepositCommand implements Command { private Cmb cmb = new Cmb(); @Override public void execute() { cmb.saveMoney(100); } @Override public void undo() { cmb.getMoney(100); } }
招行的取款命令:
public class CmbWithdrawCommand implements Command { private Cmb cmb = new Cmb(); @Override public void execute() { cmb.getMoney(100); } @Override public void undo() { cmb.saveMoney(100); } }
ATM机刚出厂时可能还没设置任何命令,所以为每个按钮预置一个什么都不做的命令:
public class NoCommand implements Command { @Override public void execute() { } @Override public void undo() { } }
现在来实现一个刚出厂的ATM机,它可能完成任何银行的存取款命令,这些命令由负责购买ATM机的银行日后自行规划:
public class Atm { private Command[] command; public Atm(){ this.command = new Command[]{new NoCommand()}; } //设置一组要执行的命令 public void setCommand(Command command[]) { this.command = command; } //执行命令的方法 public void action(int i) { this.command[i].execute(); } //撤销命令的方法 public void cancel(int i) { this.command[i].undo(); } }
现在假设要实现一个建行的ATM机,只有三个功能:1是向建行存款;2是从建行取款;3从招行取款。只要为ATM设置上相应的命令就可以了。测试类:
public class Test { /** * 命令模式——将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。 * 命令模式也支持科撤销的操作。 * * @param args */ public static void main(String[] args) { //调用者来执行命令 Atm atm = new Atm(); Command[] commands = new Command[3]; commands[0] = new CcbDepositCommand(); commands[1] = new CcbWithdrawCommand(); commands[2] = new CmbWithdrawCommand(); atm.setCommand(commands); atm.action(0); atm.cancel(0); atm.action(1); atm.cancel(1); atm.action(2); atm.cancel(2); } }
当然,如果我们不适用ATM机,直接到银行的窗口,营业员也可以直接调用系统相应的命令:
//直接执行具体命令 Command command = new CcbDepositCommand(); command.execute(); command.undo();
命令模式的扩展性、封装性很好,可以很好的将用户请求与请求的实现解耦,对需求的变化也更容易扩展。但一个很简单的请求都需要封装为一个命令,也会导致类的膨胀,因此开发时需根据实际需要判断是否使用命令模式。
相关推荐
——————————————————————————————————————————————
Java设计模式学习笔记
总结了java开发中的21种设计模式,详解和例子,带书签的pdf格式,方便阅读!
学习Java设计模式的笔记,标注了其中重要的要点,如果有需要的小伙伴,自行下载哦
Java JDK 6学习笔记——ppt简体版.rar
Java JDK 6学习笔记——ppt简体版加课本代码
Java JDK 6学习笔记——ppt简体版
良葛格————JavaJDK5.0学良葛格————JavaJDK5.0学习笔记PDF.rar习笔记PDF.rar良葛格良葛格————JavaJDK5.0学习笔记PDF.rar————JavaJDK5.0学习笔记PDF.rar良葛格————JavaJDK5.0学习笔记PDF.rar良...
java设计模式的学习笔记,其中包含各种模式的代码实现
Java JDK 6学习笔记——ppt简体版 第21章.ppt
Java JDK 6学习笔记——ppt简体版 第20章.ppt
Java JDK 6学习笔记——ppt简体版 第19章.ppt
Java JDK 6学习笔记——ppt简体版 第18章.ppt
Java JDK 6学习笔记——ppt简体版 第17章.ppt