跟萌新一起学设计模式(十三)之命令模式

**

设计模式(十三)之命令模式

**

  • 案例说明

      我们开了一家水果捞专卖店,老板是想把原先的纸质菜单换成一个类似电子遥控器样式的菜单(如下图)。店里现只有三种水果——苹果、香蕉、芒果,顾客需要加哪种水果就点哪个,这里我们就用命令模式来解决这个需求。
    在这里插入图片描述
      命令模式一般有三大角色,下达命令者、接收命令者、命令,上图中顾客就是下达命令者,水果就是接收命令者,命令就是顾客的需要与不需要的操作。命名模式使得下达命令者与接收命令者消除彼此之间的耦合,让对象之间的调用关系更加灵活,实现解耦。

    在这里插入图片描述
      我们将命令设为一个接口,接口下有三个实现的子类——点苹果的命令、点香蕉的命令和点芒果的命令,各个子类命令将各自的水果组合进去,相当于在命令类中调用水果里面的方法。菜单类将命令接口组合进去,调用菜单里面的按钮方法相当于调用命令里面的方法。

      水果实体类

public class Apple {
    // 需要加苹果
    public void order(){
        System.out.println("水果捞里加苹果");
    }

    // 不需要加苹果
    public void noOrder(){
        System.out.println("水果捞里不加苹果");
    }
}
public class Banana {
    // 需要加香蕉
    public void order(){
        System.out.println("水果捞里加香蕉");
    }

    // 不需要加香蕉
    public void noOrder(){
        System.out.println("水果捞里不加香蕉");
    }
}
public class Mango {
    // 需要加芒果
    public void order(){
        System.out.println("水果捞里加芒果");
    }

    // 不需要加芒果
    public void noOrder(){
        System.out.println("水果捞里不加芒果");
    }
}
  命令接口
public interface Command {

    // 执行需要操作
    void execute();

    // 执行不需要操作
    void undo();

}

  命令实现子类

public class AppleOrderCommand implements Command{
    private Apple apple;

    public AppleOrderCommand(Apple apple){
        this.apple = apple;
    }

    // 执行需要苹果的操作
    @Override
    public void execute() {
        apple.order();
    }

    // 执行不需要苹果的操作
    @Override
    public void undo() {
        apple.noOrder();
    }
}
public class BananaOrderCommand implements Command{
    private Banana banana;

    public BananaOrderCommand(Banana banana){
        this.banana = banana;
    }

    // 执行需要香蕉的操作
    @Override
    public void execute() {
        banana.order();
    }

    // 执行不需要香蕉的操作
    @Override
    public void undo() {
        banana.noOrder();
    }
}
public class MangoOrderCommand implements Command{
    private Mango mango;

    public MangoOrderCommand(Mango mango){
        this.mango = mango;
    }

    // 执行需要芒果的操作
    @Override
    public void execute() {
        mango.order();
    }

    // 执行不需要芒果的操作
    @Override
    public void undo() {
        mango.noOrder();
    }
}

  菜单类,默认按钮为不需要的状态,给每一排的按钮设置相应的含义,给各个按钮设置相应的方法。

public class Menu {

    // 模拟遥控器上的三个按钮
    private Command[] orderCommands;

    public Menu(){
        orderCommands = new Command[3];
        // 第一排按钮是点苹果的按钮
        orderCommands[0] = new AppleOrderCommand(new Apple());
        // 第二排按钮是点香蕉的按钮
        orderCommands[1] = new BananaOrderCommand(new Banana());
        // 第三排按钮是点芒果的按钮
        orderCommands[2] = new MangoOrderCommand(new Mango());
        // 默认按钮是不需要的状态
        for (int i = 0; i < 3; i++) {
            orderCommands[i].undo();
        }
        System.out.println("——————————————————————————————————————————————————————");
    }

    public void pushOrderBotton(int number){
        // 执行第number排按钮上的需要操作
        orderCommands[number].execute();
    }

    public void pushNoOrderBotton(int number){
        // 执行第number排按钮上的不需要操作
        orderCommands[number].undo();
    }
    
}

  客户端

public class Client {
    public static void main(String[] args) {
        Menu menu = new Menu();
        // 点击第二排需要的按钮
        menu.pushOrderBotton(1);
        // 点击第三排需要的按钮
        menu.pushOrderBotton(2);
        // 点击第二排不需要的按钮
        menu.pushNoOrderBotton(1);
    }
}

  测试,会先打印出默认设置的结果,再打印操作的历史记录。

D:\jdk8\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2\lib\idea_rt.jar=61688:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2\bin" -Dfile.encoding=UTF-8 -classpath D:\jdk8\jre\lib\charsets.jar;D:\jdk8\jre\lib\deploy.jar;D:\jdk8\jre\lib\ext\access-bridge-64.jar;D:\jdk8\jre\lib\ext\cldrdata.jar;D:\jdk8\jre\lib\ext\dnsns.jar;D:\jdk8\jre\lib\ext\jaccess.jar;D:\jdk8\jre\lib\ext\jfxrt.jar;D:\jdk8\jre\lib\ext\localedata.jar;D:\jdk8\jre\lib\ext\nashorn.jar;D:\jdk8\jre\lib\ext\sunec.jar;D:\jdk8\jre\lib\ext\sunjce_provider.jar;D:\jdk8\jre\lib\ext\sunmscapi.jar;D:\jdk8\jre\lib\ext\sunpkcs11.jar;D:\jdk8\jre\lib\ext\zipfs.jar;D:\jdk8\jre\lib\javaws.jar;D:\jdk8\jre\lib\jce.jar;D:\jdk8\jre\lib\jfr.jar;D:\jdk8\jre\lib\jfxswt.jar;D:\jdk8\jre\lib\jsse.jar;D:\jdk8\jre\lib\management-agent.jar;D:\jdk8\jre\lib\plugin.jar;D:\jdk8\jre\lib\resources.jar;D:\jdk8\jre\lib\rt.jar;D:\ideaworkspace\design_pattern\design\target\classes;D:\dev_tools\repository\org\projectlombok\lombok\1.16.10\lombok-1.16.10.jar;D:\dev_tools\repository\cglib\cglib\3.3.0\cglib-3.3.0.jar;D:\dev_tools\repository\org\ow2\asm\asm\7.1\asm-7.1.jar com.wd.command.Client
水果捞里不加苹果
水果捞里不加香蕉
水果捞里不加芒果
——————————————————————————————————————————————————————
水果捞里加香蕉
水果捞里加芒果
水果捞里不加香蕉

Process finished with exit code 0
  • 总结
      1、将发起请求的对象与执行请求的对象解耦。发起请求的对象是调用者,调用者只要调用命令对象的execute()方法就可以让接收者工作,而不必知道具体的接收者对象是谁、是如何实现的,命令对象会负责让接收者执行请求的动作,也就是说:请求发起者和请求执行者之间的解耦是通过命令对象实现的,命令对象起到 了纽带桥梁的作用;
      2、可以设计一个命令队列,只要把命令对象放到列队,就可以多线程的执行命令;
      3、命令模式不足:可能导致某些系统有过多的具体命令类,增加了系统的复杂度,这
    点在在使用的时候要注意。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值