1. 程式人生 > >Java設計模式12:命令模式

Java設計模式12:命令模式

一、什麼是命令模式?

在閻巨集博士的《JAVA與模式》一書中開頭是這樣描述命令(Command)模式的:

命令模式屬於物件的行為模式。命令模式又稱為行動(Action)模式或交易(Transaction)模式。

命令模式把一個請求或者操作封裝到一個物件中。命令模式允許系統使用不同的請求把客戶端引數化,對請求排隊或者記錄請求日誌,可以提供命令的撤銷和恢復功能。

二 、命令模式涉及到五個角色,它們分別是:

  ●  客戶端(Client)角色:建立一個具體命令(ConcreteCommand)物件並確定其接收者。

  ●  命令(Command)角色:聲明瞭一個給所有具體命令類的抽象介面。

  ●  具體命令(ConcreteCommand)角色:定義一個接收者和行為之間的弱耦合;實現execute()方法,負責呼叫接收者的相應操作。execute()方法通常叫做執行方法。

  ●  請求者(Invoker)角色:負責呼叫命令物件執行請求,相關的方法叫做行動方法。

  ●  接收者(Receiver)角色:負責具體實施和執行一個請求。任何一個類都可以成為接收者,實施和執行請求的方法叫做行動方法。

三、程式碼案例場景:

每個人家裡都有電視機,電視機由遙控控制。我們簡單化,只有增加音量、降低音量、改變頻道三個命令。電視機是接受者,遙控器是請求者,增加音量、降低音量、改變頻道就是具體的命令類,我們人就是客戶端。

程式碼示例:

先建立一個接受者電視類

/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/10/18 20:06
 *    @desc   : 命令模式中的接受者類
 *    @version: 1.0
 * </pre>
 */
public class Television {

    public void addVolume(){
        System.out.println("增加音量");
    }

    public void reduceVolume(){
        System.out.println("降低音量");
    }

    public void changeChannel(){
        System.out.println("改變頻道");
    }

}

抽象命令介面:

/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/10/18 20:11
 *    @desc   : 抽象命令角色類
 *    @version: 1.0
 * </pre>
 */
public interface Command {

    public void execute();
}

增加音量、降低音量、改變頻道三個具體命令實現類:

/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/10/19 09:30
 *    @desc   : 具體命令操作類
 *    @version: 1.0
 * </pre>
 */
public class AddVolumeCommand implements Command {

    private Television television;

    public AddVolumeCommand(Television television){
        this.television = television;
    }

    @Override
    public void execute() {
        television.addVolume();
    }
}

 

/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/10/19 09:32
 *    @desc   : 具體命令操作類
 *    @version: 1.0
 * </pre>
 */
public class ReduceVolumeCommand implements Command{

    private Television television;

    public ReduceVolumeCommand (Television television){
        this.television = television;
    }

    @Override
    public void execute() {
        television.reduceVolume();
    }
}
/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/10/19 09:36
 *    @desc   : 具體命令操作類
 *    @version: 1.0
 * </pre>
 */
public class ChangeChannelCommand implements Command{

    private Television television;

    public ChangeChannelCommand(Television television){
        this.television = television;
    }

    @Override
    public void execute() {
        television.changeChannel();
    }
}

 請求者類:


/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/10/19 09:38
 *    @desc   : 請求者遙控類
 *    @version: 1.0
 * </pre>
 */
public class RemoteControl {

   /* private Command command;

    public RemoteControl(Command command){
        this.command = command;
    }

    public void execute(){
        command.execute();
    }*/

    private AddVolumeCommand addVolumeCommand;
    private ReduceVolumeCommand reduceVolumeCommand;
    private ChangeChannelCommand changeChannelCommand;

    public void setAddVolumeCommand(AddVolumeCommand addVolumeCommand) {
        this.addVolumeCommand = addVolumeCommand;
    }

    public void setChangeChannelCommand(ChangeChannelCommand changeChannelCommand) {
        this.changeChannelCommand = changeChannelCommand;
    }

    public void setReduceVolumeCommand(ReduceVolumeCommand reduceVolumeCommand) {
        this.reduceVolumeCommand = reduceVolumeCommand;
    }


    public void addVolumeCommand(){
        addVolumeCommand.execute();
    }

    public void reduceVolumeCommand(){
        reduceVolumeCommand.execute();
    }

    public void changeChannelCommand(){
        changeChannelCommand.execute();
    }
}

最後客戶端測試:


/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/10/19 09:49
 *    @desc   : 客戶端車測試
 *    @version: 1.0
 * </pre>
 */
public class Client {


    public static void main(String[] args){
        Television television = new Television();

        AddVolumeCommand addVolumeCommand = new AddVolumeCommand(television);
        ReduceVolumeCommand reduceVolumeCommand = new ReduceVolumeCommand(television);
        ChangeChannelCommand changeChannelCommand = new ChangeChannelCommand(television);

        RemoteControl remoteControl = new RemoteControl();
        remoteControl.setAddVolumeCommand(addVolumeCommand);
        remoteControl.setReduceVolumeCommand(reduceVolumeCommand);
        remoteControl.setChangeChannelCommand(changeChannelCommand);

        remoteControl.addVolumeCommand();
        remoteControl.reduceVolumeCommand();
        remoteControl.changeChannelCommand();

    }





}

四、總結:

命令模式是對命令的封裝。命令模式把發出命令的責任和執行命令的責任分割開,委派給不同的物件。

  每一個命令都是一個操作:請求的一方發出請求要求執行一個操作;接收的一方收到請求,並執行操作。命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的介面,更不必知道請求是怎麼被接收,以及操作是否被執行、何時被執行,以及是怎麼被執行的。

  命令允許請求的一方和接收請求的一方能夠獨立演化,從而具有以下的優點:

  (1)命令模式使新的命令很容易地被加入到系統裡。

  (2)允許接收請求的一方決定是否要否決請求。

  (3)能較容易地設計一個命令佇列。

  (4)可以容易地實現對請求的撤銷和恢復。

  (5)在需要的情況下,可以較容易地將命令記入日誌。