Java设计模式 之 命令模式

 

1      从属模式分类

 

行为性模式

2      命令模式意图

命令模式可将动作的请求者和动作的执行者对象中解耦。

该模式将一个行为操作发起者的请求封装到对象中,该请求由另外一个对象执行。

将动作封装成命令对象,这样一来就可以随心所欲的储存、传递、调用。

做多件事,有多种做法。

3      命令模式结构

 

4      命令模式代码实现

这里假设有一个需要编程实现功能的遥控器,一共有10组开关按钮需要编程来实现不同的控制逻辑。比如说第一组开关可控制客厅的电灯的开关,第二组开关按钮可控制车库门的升起和落下,使用命令模式代码如下:

4.1    ICommon.java

package com.gof.pattern.command;

 

/**

 * 命令接口

 * @author Administrator

 */

 

public interface ICommand {

   

    // 执行

    public void execute();

   

    // 撤销

    public void undo();

   

}

4.2    Light.java

package com.gof.pattern.command;

 

/**

 * 电灯

 * @author Administrator

 */

 

public class Light {

   

    private Stringname;

   

    public Light(String name){

       this.name = name;

    }

   

    public void on(){

       System.out.println(name +" light is on!");

    }

   

    public void off(){

       System.out.println(name +" light is off!");

    }

 

}

 

4.3    LightOnCommand.java

package com.gof.pattern.command;

 

public class LightOnCommand implements ICommand {

   

    private Lightlight;

   

    public LightOnCommand(Light light){

       this.light = light;

    }

 

    @Override

    public void execute() {

       light.on();

    }

 

    @Override

    public void undo() {

       light.off();

    }

}

4.4    LightOffCommand.java

package com.gof.pattern.command;

 

/**

 * 关灯

 * @author Administrator

 *

 */

 

public class LightOffCommand implements ICommand {

   

    private Lightlight;

   

    public LightOffCommand(Light light){

       this.light = light;

    }

 

    @Override

    public void execute() {

       light.off();

    }

 

    @Override

    public void undo() {

       light.on();

    }

}

4.5    Stereo.java

package com.gof.pattern.command;

 

/**

 * 音响

 * @author Administrator

 */

 

public class Stereo {

   

    private Stringname;

   

    public Stereo(String name){

       this.name = name;

    }

   

    public void on(){

       System.out.println(name +" is on!");

    }

   

    public void off(){

       System.out.println(name +" is off!");

    }

   

    public void setCd(){

       System.out.println(name +" setCd!");

    }

   

    public void setDvd(){

       System.out.println(name +" setDvd!");

    }

   

    public void setRadio(){

       System.out.println(name +" setRadio!");

    }

 

    public void setVolume(int size){

       System.out.println(name +" setVolume is "+ size +"!");

    }

}

 

4.6    StereoOffWithCDCommand.java

package com.gof.pattern.command;

 

/**

 * 关闭音响

 * @author Administrator

 *

 */

 

public class StereoOffWithCDCommand implements ICommand {

   

    private Stereostereo;

   

    public StereoOffWithCDCommand(Stereo stereo){

       this.stereo = stereo;

    }

 

    @Override

    public void execute() {

       stereo.off();

    }

 

    @Override

    public void undo() {

       stereo.setCd();

       stereo.setVolume(11);

       stereo.on();

    }

 

}

4.7    StereoOnWithCDCommand.java

package com.gof.pattern.command;

 

/**

 * 打开音响

 * @author Administrator

 *

 */

 

public class StereoOnWithCDCommand implements ICommand {

   

    private Stereostereo;

   

    public StereoOnWithCDCommand(Stereo stereo){

       this.stereo = stereo;

    }

 

    @Override

    public void execute() {

       stereo.setCd();

       stereo.setVolume(11);

       stereo.on();

    }

 

    @Override

    public void undo() {

       stereo.off();

    }

}

 

4.8    GarageDoor.java

package com.gof.pattern.command;

 

/**

 * 车库实体类

 * @author Administrator

 *

 */

 

public class GarageDoor {

   

    private Stringname;

   

    public GarageDoor(String name){

       this.name = name;

    }

   

    public void up(){

       System.out.println(name +" is up!");

    }

   

    public void down(){

       System.out.println(name +" is down!");

    }

 

}

 

4.9    GarageDoorUpCommand.java

package com.gof.pattern.command;

 

/**

 * 车库门升起

 * @author Administrator

 */

 

public class GarageDoorUpCommand implements ICommand {

   

    private GarageDoorgarageDoor;

   

    public GarageDoorUpCommand(GarageDoor garageDoor){

       this.garageDoor = garageDoor;

    }

 

    @Override

    public void execute() {

       garageDoor.up();

    }

 

    @Override

    public void undo() {

       garageDoor.down();

    }

 

}

 

4.10       GarageDoorDownCommand.java

package com.gof.pattern.command;

 

/**

 * 车库们落下

 * @author Administrator

 */

 

public class GarageDoorDownCommand implements ICommand {

   

    private GarageDoorgarageDoor;

   

    public GarageDoorDownCommand(GarageDoor garageDoor){

       this.garageDoor = garageDoor;

    }

 

    @Override

    public void execute() {

       garageDoor.down();

    }

 

    @Override

    public void undo() {

       garageDoor.up();

    }

 

}

 

4.11       NoCommand.java

package com.gof.pattern.command;

 

/**

 * 空命令

 * @author Administrator

 *

 */

 

public class NoCommand implements ICommand {

 

    @Override

    public void execute() {}

 

    @Override

    public void undo() {}

 

}

4.12       RemoteControl.java

package com.gof.pattern.command;

 

/**

 * 遥控器

 * @author Administrator

 */

 

public class RemoteControl {

   

    private ICommand[]onCommands;

   

    private ICommand[]offCommands;

   

    private ICommandundoCommand;

   

    // 初始化遥控器按钮功能

    public RemoteControl(){

       onCommands = new ICommand[7];

       offCommands = new ICommand[7];

       ICommand noCommand = new NoCommand();

       for(int i=0; i<7; i++){

           onCommands[i] = noCommand;

           offCommands[i] = noCommand;

       }

       undoCommand = noCommand;

    }

   

    public void setCommand(int slot, ICommand onCommand, ICommand offCommand){

       onCommands[slot] = onCommand;

       undoCommand.undo();

       offCommands[slot] = offCommand;

    }

   

    // 按某个位置,on按钮

    public void onButtonWasPushed(int solt){

       onCommands[solt].execute();

       undoCommand = onCommands[solt];

    }

   

    // 按某个位置,off按钮

    public void offButtonWasPushed(int solt){

       offCommands[solt].execute();

       undoCommand = offCommands[solt];

    }

   

    // undo按钮

    public void undoButtonWasPushed(){

 

    }

   

    @Override

    public String toString(){

       StringBuffer stringBuff = new StringBuffer();

       stringBuff.append("\n------ Remote Control ------\n");

       for(int i=0; i<onCommands.length; i++){

           stringBuff.append("[solt "+ i +"]" +onCommands[i].getClass().getName() +

                  "    " +offCommands[i].getClass().getName() +"\n");

       }

       return stringBuff.toString();

    }

 

}

 

4.13       RemoteLoader.java 遥控器测试类

package com.gof.pattern.command;

 

public class RemoteLoader {

 

    public static void main(String[] args) {

      

       // 创建一个遥控器

       RemoteControl remoteControl = new RemoteControl();

      

       // 将所有装置创建在合适位置

       Light livingRoomLight = new Light("Living Room");

       Light kitchenLight = new Light("Kitchen");

       GarageDoor garageDoor = new GarageDoor("");

       Stereo stereo = new Stereo("Living Room");

      

       // 创建所有电灯命令对象

       ICommand livingRoomLightOn = new LightOnCommand(livingRoomLight);

       ICommand livingRoomLightOff = new LightOffCommand(livingRoomLight);

       ICommand kitchenLightOn = new LightOnCommand(kitchenLight);

       ICommand kigcchenLightOff = newLightOffCommand(kitchenLight);

       // 创建车库门上下命令对象

       ICommand garageDoorUp = new GarageDoorUpCommand(garageDoor);

       ICommand garageDoorDown = new GarageDoorDownCommand(garageDoor);

       // 创建音响开关命令对象

       ICommand stereoOnWithCDCommand = new StereoOnWithCDCommand(stereo);

       ICommand stereoOffWithCdCommand = new StereoOffWithCDCommand(stereo);

      

       // 为遥控器某个位置设置命令

       remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);

       remoteControl.setCommand(1, kitchenLightOn, kigcchenLightOff);

       remoteControl.setCommand(2, garageDoorUp, garageDoorDown);

       remoteControl.setCommand(3, stereoOnWithCDCommand, stereoOffWithCdCommand);

      

       System.out.println(remoteControl);

      

       // 我们按下遥控器上的1234开关按钮测试

       remoteControl.onButtonWasPushed(0);

       remoteControl.offButtonWasPushed(0);

      

       remoteControl.onButtonWasPushed(1);

       remoteControl.offButtonWasPushed(1);

      

       remoteControl.onButtonWasPushed(2);

       remoteControl.offButtonWasPushed(2);

      

       remoteControl.onButtonWasPushed(3);

       remoteControl.offButtonWasPushed(3);

      

       remoteControl.undoButtonWasPushed();

    }

}

 

 

5      命令模式总结

5.1    优点

降低了决策逻辑的复杂性

提供了可扩展能力

能够方便地提供撤销操作

能够将多个命令放在一个队列中

能够在不同的线程或远程执行命令

5.2    缺点

在对象的创建、销毁及使用过程中可能会增加系统开销

使应用程序的结构更加复杂

5.3    指导原则

封装变化

多用组合,少用继承

针对接口编程,不针对实现编程

为交互对象之间松耦合设计而努力

类应该对扩展开发,对修改关闭

依赖抽象,不依赖具体类

命令模式:将请求封装成对象,这可以让你使用不同的请求、队列、或者日志请求来参数化其它对象。命令模式也可以支持撤销操作。

 


posted @ 2015-09-07 17:00  dcz1001  阅读(182)  评论(0编辑  收藏  举报