设计模式之命令模式

命令模式

1.需求

买了一套智能家电(如照明灯,风扇,洗衣机等等),但是不想每一个家电都用一个对应的app去控制,想做到使用一个“遥控器”统一控制所有电器

2.分析需求
  • 如果想实现一个app控制其他所有家电,则其他家电都要提供一个统一的接口给app调用,可以尝试把命令接收全部进行抽象化,附着在“家电”上。
  • 同时可以考虑使用命令模式
3.命令模式的基本介绍
  1. 命令模式(Command Pattern),可以将一个请求封装为一个对象,以便于使用不同参数表达不同的请求。
  2. 命令模式使得请求发送者和接收者之间消除彼此的耦合,让对象之间的调用关系变得灵活
  3. 命令模式中存在的角色:
    • 抽象命令类(Command):声明执行命令的接口,拥有执行命令的抽象方法
    • 具体命令类(Concrete Command),抽象命令的具体化,内部组合receiver
    • 实现者(接收者)(Receiver),执行命令功能的相关操作,是具体命令业务的真正实现者
    • 调用者(请求者)(invoker),是请求的发送者,它通常拥有很多的命令对象(list or array),通常访问命令对象从而实现某些命令

4.uml
在这里插入图片描述

4.“遥控器”的代码实现

在这里插入图片描述
uml

在这里插入图片描述

package com.liz.GOF23.command.command_controller.command;

//创建命令接口(命令的抽象)
public interface MyCommand {
    //执行某个命令
    public void execute();
    //撤销某个命令
    public void undo();
}

//具体命令类
/**
 * 没有任何命令,即空执行:用于初始化状态【默认】
 * 使用NoCommand 可以省略对空的判断
 * */
public class NoCommand implements MyCommand {
    //聚合 LightReceiver,从而执行具体的命令
    private MyReceiver light;

    public NoCommand(){
    }
    @Override
    public void execute() {
        //调用接收者的方法

    }

    @Override
    public void undo() {
        //调用接收者的方法

    }
}
//命令对象(内部聚合了receiver进行具体操作)
//关灯操作
public class LightOffCommand implements MyCommand {
    //聚合 LightReceiver,从而执行具体的命令
    private MyReceiver light;

    public LightOffCommand(MyReceiver light){
        this.light = light;
    }
    @Override
    public void execute() {
        //调用接收者的方法
        light.off();
    }

    @Override
    public void undo() {
        //调用接收者的方法
        light.on();
    }
}
//命令对象(内部聚合了接收者进行具体操作)
//开灯操作
public class LightOnCommand implements MyCommand {
    //聚合 LightReceiver,从而执行具体的命令
    private MyReceiver light;

    public LightOnCommand(MyReceiver light){
        this.light = light;
    }
    @Override
    public void execute() {
        //调用接收者的方法
        light.on();
    }

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

//抽象接收者

//Receiver
public interface MyReceiver {
     //开启
     void on();
     //关闭
     void off();
}
//具体的接收者
public class LightReceiver implements MyReceiver {
    public void on(){
        System.out.println(" 电灯打开了 ");
    }
    public void off(){
        System.out.println(" 电灯关闭了 ");
    }
}
/**
 * Invoker
 * 命令的发送者:内部放置了多个命令
 */
public class RemoteInvoker {
    //命令集合1[开启]
    MyCommand[] onCommands;
    //命令集合2[关闭]
    MyCommand[] offCommands;
    //命令 [撤销]
    MyCommand undoCommand;

    //构造器 完成初始化【初始化每一个指令 => 空操作】
    public RemoteInvoker() {
        onCommands = new MyCommand[5];
        offCommands = new MyCommand[5];

        //将所有的指令默认初始化
        for (int i = 0; i < 5; i++) {
            onCommands[i] = new NoCommand();
            offCommands[i] = new NoCommand();
        }
    }

    //给按钮设置需要的命令即可

    //!!!!给控制器动态设置指令
    public void setCommand(int no, MyCommand onCommand, MyCommand 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 undoButtonWasPushed(){
        undoCommand.undo();
    }

}
//测试类
public class Client {
    public static void main(String[] args) {
        //使用命令设计模式,通过遥控对电灯的操作
        //创建电灯接收者
        MyReceiver receiver = new LightReceiver();

        //创建电灯开闭的命令(MyReceiver 和 command进行绑定)
        LightOnCommand onCommand = new LightOnCommand(receiver);
        LightOffCommand offCommand = new LightOffCommand(receiver);

        //遥控器
        RemoteInvoker controller = new RemoteInvoker();
        controller.setCommand(0,onCommand,offCommand);

        //遥控器调用命令
        System.out.println("-------------按下开启按钮----------------");
        controller.onButtonWasPushed(0);
        System.out.println("--------------撤销操作------------------");
        controller.undoButtonWasPushed();
        System.out.println("--------------按下关闭按钮-----------------");
        controller.offButtonWasPushed(0);
        System.out.println("--------------撤销操作------------------");
        controller.undoButtonWasPushed();
    }
}

执行结果:
在这里插入图片描述

命令模式的细节
  • 将发起请求和执行请求的对象进行解耦,发起请求的对象是调用者,调用者(invoker)只要调用命令对象的方法就可以让接收者进行工作,但是并不需要知道具体的接收者(LightOnReceiver)是谁,命令对象(xxCommand)负责让接收者进行执行请求的动作。

  • 因此命令对象实现了纽带的作用,将发送者和接收者进行联系

  • 命令对象的优缺点:

    • 优点: 实现低耦合,新的命令可以很容易添加到系统中去
    • 缺点: 可能导致某些系统有过多的命令类,增加系统的复杂度
  • 命令模式的使用环境:

    • 设置界面按钮和指令,模拟CMS (DOS)命令订单的撤销和恢复,实现触发反馈机制

参考资料: 韩顺平java设计模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值