命令模式(Command)----设计模式

命令模式(Command)----设计模式

命令模式,简单的讲,就是将**“命令动作的请求者""命令动作的执行者”**进行解耦,并要求请求可以撤销的。

生活中也处处可见命令模式:

老板发布一个命令,不是直接发布到了员工手中,而是发布给了秘书,具体怎么执行这个命令,交给秘书来完成;再或者一个多用遥控器,上面有很多的家用电器的开关按钮,此时你就可以通过这一个遥控器操控所有电器,而具体电器的开关不与你直接相关…

什么是命令模式?

命令模式(Command Pattern),在软件设计中,我们经常需要向某些对象发送请求,但是具体不知道请求的接收者是谁,也不知道被请求的操作是哪一个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来设计。

命令模式使得请求发送者与请求接收者消除彼此之间得耦合,让对象之间的调用关系更加灵活,实现解耦。

在命令模式中,会将一个请求封装为一个对象,以便使用不同参数来表示不同的请求(即命令),同时命令模式也支持撤销操作。

应该会有小伙伴们感觉到迷糊,其实最初我也很迷糊的,下面一会让我们看个具体的多用遥控器的实现过程可能就清楚啦~

命令模式中的几个部分

  1. Command:

    定义命令的接口,声明执行的方法。

  2. ConcreteCommand(以下demo中,电灯、电视的开关动作都为此类):

    命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。

  3. Receiver(电灯LightRecever、电视类TVRecever):

    接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。

    通常聚合在ConcreteCommand中。

  4. Invoker(RemoteController遥控器):

    要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

  5. Client:

    创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。

命令模式的类图

在这里插入图片描述

多用遥控器案例实现

command接口

package com.design_patterns.command;

//创建命令接口
public interface Command {
    
    

    //执行动作(操作)
    public void execute();
    //撤销动作(操作)
    public void undo();

}

LightOnCommand电灯打开执行类

package com.design_patterns.command;

public class LightOnCommand implements Command {
    
    

    private LightReceiver lightReceiver;

    //构造方法

    public LightOnCommand(LightReceiver lightReceiver) {
    
    
        this.lightReceiver = lightReceiver;
    }

    //聚合LightReceiver
    @Override
    public void execute() {
    
    
         //调用接收者的方法
        lightReceiver.on();
    }

    @Override
    public void undo() {
    
    
        //调用接收者的方法
        lightReceiver.off();
    }
}

LightOffCommand电灯关闭执行类

package com.design_patterns.command;

public class LightOffCommand implements Command {
    
    

    private LightReceiver lightReceiver;

    //构造方法
    public LightOffCommand(LightReceiver lightReceiver) {
    
    
        this.lightReceiver = lightReceiver;
    }

    //执行关闭的方法
    @Override
    public void execute() {
    
    
        this.lightReceiver.off();
    }


    //执行撤销命令
    @Override
    public void undo() {
    
    
        this.lightReceiver.on();
    }
}

TVOnCommand电视机打开执行类

package com.design_patterns.command;

public class TVOnCommand implements Command {
    
    

    //聚合tv接收者
    private TVReceiver tvReceiver;

    //通过构造方法传递进来实际的tv接收者
    public TVOnCommand(TVReceiver tvReceiver) {
    
    
        this.tvReceiver = tvReceiver;
    }

    @Override
    public void execute() {
    
    
        //使接收者执行动作命令
        this.tvReceiver.on();
    }

    @Override
    public void undo() {
    
    
        //撤回操作
        this.tvReceiver.off();
    }
}

NoCommand无命令类,用于初始化操作

package com.design_patterns.command;


/**
 * 无任何命令,即空执行。
 * 用于初始化每个按钮,当调用空命令时,对象什么都不做
 * 其实,这样也是一种设计模式,可以省略对空命令的判断
 */
public class NoCommand implements Command {
    
    
    @Override
    public void execute() {
    
    

    }

    @Override
    public void undo() {
    
    

    }
}

TVOffCommand电视机关闭执行类

package com.design_patterns.command;

public class TVOffCommand implements Command {
    
    

    private TVReceiver tvReceiver;

    public TVOffCommand(TVReceiver tvReceiver) {
    
    
        this.tvReceiver = tvReceiver;
    }

    @Override
    public void execute() {
    
    
        this.tvReceiver.off();
    }

    @Override
    public void undo() {
    
    
        this.tvReceiver.on();
    }
}

LightReceiver电灯接收者类

package com.design_patterns.command;

public class LightReceiver {
    
    

    public void on(){
    
    
        System.out.println("电灯打开了!");
    }

    public  void off(){
    
    
        System.out.println("电灯关闭了!");
    }
}

TVReceiver电视接收者类

package com.design_patterns.command;

public class TVReceiver {
    
    

    public void on(){
    
    
        System.out.println("电视TV打开了!");
    }

    public void off(){
    
    
        System.out.println("电视TV关闭了!");
    }
}

RemoteController发出请求的invoker多用遥控器类

package com.design_patterns.command;

public class RemoteController {
    
    

    //开 按钮的命令数组
    Command[] onCommands;
    Command[] offCommands;


    //执行撤销的命令
    Command undoCommand;

    public RemoteController() {
    
    
        onCommands = new Command[5];
        offCommands = new Command[5];

        for (int i = 0; i < 5; i++){
    
    
            onCommands[i] = new NoCommand();
            offCommands[i] = new NoCommand();
        }
    }


    //为我们的按钮设置你所需要的命令
    public void setCommand(int no, Command onCommand, Command offCommand){
    
    
        onCommands[no] = onCommand;
        offCommands[no] = offCommand;
    }


    //按下开的按钮
    public void onButtonWasPushed(int no){
    
    
        // 找到你按下的按钮,并调用对应的方法
        onCommands[no].execute();
        //记录这次的操作,用于撤销
        undoCommand = onCommands[no];
    }


    //按下关的按钮
    public void offButtonWasPushed(int no){
    
    
        // 找到你按下的按钮,并调用对应的方法
        offCommands[no].execute();
        //记录这次的操作,用于撤销
        undoCommand = offCommands[no];
    }


    //按下撤销按钮
    public void undoButtonWasPush(){
    
    
        //撤销上次的动作
        undoCommand.undo();
    }

}

Client客户端

package com.design_patterns.command;

import javafx.scene.effect.Light;

public class Client {
    
    
    public static void main(String[] args) {
    
    
        //使用命令设计模式,完成通过遥控器,对电灯的操作

        /**
         * 创建电灯的对象(接收者)
         */
        LightReceiver lightReceiver = new LightReceiver();

        //创建电灯相关的开关命令
        LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
        LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);


        //创建一个遥控器
        RemoteController remoteController = new RemoteController();

        //给我们的遥控器设置相关的命令,比如 no = 0 使电灯的开和关的操作
        remoteController.setCommand(0,lightOnCommand,lightOffCommand);


        System.out.println("----按下灯的开的按钮----");
        remoteController.onButtonWasPushed(0);
        System.out.println("----按下灯的关的按钮----");
        remoteController.offButtonWasPushed(0);

        System.out.println("----撤销的操作----");
        remoteController.undoButtonWasPush();


        /**
         * 创建电视TV的对象(接收者)
         */
        TVReceiver tvReceiver = new TVReceiver();

        //创建电视TV相关的开关命令
        TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);
        TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);

        //给我们的遥控器设置相关的命令,比如 no = 1 使用电视TV的开和关的操作
        remoteController.setCommand(1,tvOnCommand,tvOffCommand);


        System.out.println("----按下电视TV的开的按钮----");
        remoteController.onButtonWasPushed(1);
        System.out.println("----按下电视TV的关的按钮----");
        remoteController.offButtonWasPushed(1);

        System.out.println("----撤销的操作----");
        remoteController.undoButtonWasPush();

    }
}

运行结果

----按下灯的开的按钮----
电灯打开了!
----按下灯的关的按钮----
电灯关闭了!
----撤销的操作----
电灯打开了!
----按下电视TV的开的按钮----
电视TV打开了!
----按下电视TV的关的按钮----
电视TV关闭了!
----撤销的操作----
电视TV打开了!

总结

命令模式最主要的功能就是实现了请求端执行端的分离,通过一个请求对象来接收请求,调用执行端执行操作,同样命令模式也实现了动作的撤销操作,更加提高了程序的健壮性。

好啦,这就是命令模式,如果有小伙伴们不理解,欢迎下方留言评论~

猜你喜欢

转载自blog.csdn.net/weixin_43479947/article/details/108457716
今日推荐