1.定义
将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
2.使用场景
需要抽象出待执行的动作,然后以参数的形式提供出来,类似于过程设计中的回调机制。
在不同的时刻指定、排列和执行请求。
需要支持取消操作。
支持修改日志功能。
需要支持事物操作。
3.简单实现
以一个电视遥控器功能为例,遥控器能控制电视机的开机、关机、调解音量、切换频道。
//定义一个接收者角色,真正具体处理逻辑的方法 class TvFunction{ //执行开机 void PowerOn(){ System.out.println("底层调用硬件通电...开机"); } //执行关机 void PowerOff(){ System.out.println("底层调用硬件断电...关机"); } //执行频道切换 void ChangeChannal(){ System.out.println("调用底层程序代码...切换频道"); } //执行音量调节 void TurnVoice(){ System.out.println("调用底层程序代码...调节音量"); } } interface Command{ //命令执行的方法 void execute(); } //开机命令 class PowerOn implements Command{ //持有一个接收者的引用 private TvFunction function; public PowerOn(TvFunction function) { this.function = function; } @Override public void execute() { //调用具体的开机方法 function.PowerOn(); } } //关机命令 class PowerOFF implements Command{ //持有一个接收者的引用 private TvFunction function; public PowerOFF(TvFunction function) { this.function = function; } @Override public void execute() { //调用具体的关机机方法 function.PowerOff(); } } //频道切换命令 class Channal implements Command{ //持有一个接收者的引用 private TvFunction function; public Channal(TvFunction function) { this.function = function; } @Override public void execute() { //调用具体的切换频道方法 function.ChangeChannal(); } } //音量调节命令 class Voice implements Command{ //持有一个接收者的引用 private TvFunction function; public Voice(TvFunction function) { this.function = function; } @Override public void execute() { //调用具体的音量调节方法 function.TurnVoice(); } } //定义请求者 遥控器 class TvContorllor{ private PowerOn powerOn; //开机对象的引用 private PowerOFF powerOFF; //关机对象的引用 private Channal channal; //频道切换对象的引用 private Voice voice; //音量调节对象的引用 public void setPowerOn(PowerOn powerOn) { this.powerOn = powerOn; } public void setPowerOFF(PowerOFF powerOFF) { this.powerOFF = powerOFF; } public void setChannal(Channal channal) { this.channal = channal; } public void setVoice(Voice voice) { this.voice = voice; } //开机 public void powerOn(){ powerOn.execute(); } //关机 public void powerOff(){ powerOFF.execute(); } //调解音量 public void turnVoice(){ voice.execute(); } //切换频道 public void changeChannal(){ channal.execute(); } } public class CommandMode { public static void main(String[] args){ //首先要有电视机的功能 TvFunction function = new TvFunction(); //构造4种命令 PowerOn powerOn = new PowerOn(function); PowerOFF powerOFF = new PowerOFF(function); Channal channal = new Channal(function); Voice voice = new Voice(function); //构造一个遥控器 TvContorllor tvContorllor = new TvContorllor(); tvContorllor.setPowerOn(powerOn); tvContorllor.setPowerOFF(powerOFF); tvContorllor.setChannal(channal); tvContorllor.setVoice(voice); //用户可以随便按遥控器控制电视 tvContorllor.powerOn(); tvContorllor.changeChannal(); tvContorllor.turnVoice(); tvContorllor.powerOff(); }
输出:
调用逻辑做的如此复杂,原因是为了代码交给别人来维护时,比较清晰,遵循了设计模式重要原则:对修改关闭对拓展开放。此外,还有一个好处是可以再TvContorllor类中存储执行过的命令,我们可以方便知道执行过哪些命令,还可以恢复。
4.小结
优点:
更弱的耦合性,更灵活的控制性,更好的拓展性;
缺点:
类的膨胀,大量的衍生类