博客信息

命令模式Command(行为模式)

发布时间:『 2019-03-30 02:52』  博客类别:23种设计模式  阅读(717)
  • 术语

    • Command:命令

    • ConcreteCommand:具体的命令

    • Invoker:调用者

    • Receiver:接受者

标准UML类图

小李飞刀_设计模式


  • 角色

    • Command 抽象命令 执行命令 撤销命令

    • ConcreteCommand LightOnCommand 开灯 LightOffCommand 关灯

      NonCommand

      空命令

    • Invoker 调用者 遥控器聚合所有命令 Command[] ons Command[] offs Command undo

    • Receiver 接受者 电灯、空调、电视

  • 案例

    需求:万能遥控器的制作

    案例UML类图

小李飞刀_设计模式



    • 出现前

      package com.javaxl.design.command.before;

      /**
      * @author 小李飞刀
      * @site www.javaxl.com
      * @company
      * @create  2020-02-24 18:14
      *
      * 被操作的对象
      */
      public class Light {
        public void on(){
            System.out.println("电灯打开...");
        }

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

      class AirConditioner {
        public void on(){
            System.out.println("空调打开...");
        }

        public void off(){
            System.out.println("空调关闭...");
        }
      }

      class Television {
        public void on(){
            System.out.println("电视打开...");
        }

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


      public class Invoker {
        private Light light = new Light();
        private AirConditioner airConditioner = new AirConditioner();
        private Television television = new Television();

        public void lightOn(){
            light.on();
        }

        public void lightOff(){
            light.off();
        }

        public void airOn(){
            airConditioner.on();
        }

        public void airOff(){
            airConditioner.off();
        }

        public void tvOn(){
            television.on();
        }

        public void tvOff(){
            television.off();
        }
      }

      public class Client {
        public static void main(String[] args) {
            Invoker invoker = new Invoker();
            invoker.lightOn();
            invoker.lightOff();
            System.out.println("=============");
            invoker.airOn();
            invoker.airOff();
            System.out.println("=============");
            invoker.tvOn();
            invoker.tvOff();
        }
      }

    • 出现后

      package com.javaxl.design.command.after;

      /**
      * @author 小李飞刀
      * @site www.javaxl.com
      * @company
      * @create  2020-02-24 18:14
      *
      * 被操作的对象
      */
      public class Light {
        public void on(){
            System.out.println("电灯打开...");
        }

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

      class AirConditioner {
        public void on(){
            System.out.println("空调打开...");
        }

        public void off(){
            System.out.println("空调关闭...");
        }
      }

      class Television {
        public void on(){
            System.out.println("电视打开...");
        }

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


      package com.javaxl.design.command.after;

      /**
      * @author 小李飞刀
      * @site www.javaxl.com
      * @company
      * @create  2020-02-24 18:25
      */
      interface Command {
        void execute();

        void undo();
      }

      //空命令
      class NonCommand implements Command {

        @Override
        public void execute() {

        }

        @Override
        public void undo() {

        }
      }

      class LightOnCommand implements Command {
        private Light light = new Light();

        @Override
        public void execute() {
            light.on();
        }

        @Override
        public void undo() {
            light.off();
        }
      }

      class LightOffCommand implements Command {
        private Light light = new Light();

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

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

      class TvOnCommand implements Command {
        private Television tv = new Television();

        @Override
        public void execute() {
            tv.on();
        }

        @Override
        public void undo() {
            tv.off();
        }
      }

      class TvOffCommand implements Command {
        private Television tv = new Television();

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

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


      public class Invoker {
        Command[] ons;
        Command[] offs;
      //   记录上一个命令
        Command command;

        public Invoker(int n) {
            ons = new Command[n];
            offs = new Command[n];
            command = new NonCommand();
            for (int i = 0; i < n; i++) {
                setCommand(i,new NonCommand(),new NonCommand());
            }
        }

        public void setCommand(int no, Command on, Command off){
            ons[no]=on;
            offs[no]=off;
        }

        public Command getOnCommand(int no){
            return ons[no];
        }

        public Command getOffCommand(int no){
            return offs[no];
        }

      //   执行命令
        public void invoke(Command command){
      //       执行当前命令
            command.execute();
      //       保存当前执行命令
            this.command = command;
        }

      //   撤销命令(上个操作的反操作)
        public void undo(){
      //       这里就能体现定义一个空命令的好处了,如果第一次按撤销命令,那么应该什么都不做;
      //       如果没有定义空命令的话,此时就需要判断空处理了
            command.undo();
        }
      }


      public class Client {
        public static void main(String[] args) {
            Invoker invoker = new Invoker(2);
            invoker.setCommand(0, new LightOnCommand(), new LightOffCommand());
            invoker.setCommand(1, new TvOnCommand(), new TvOffCommand());

            System.out.println("电灯打开关闭操作===========");
            invoker.invoke(invoker.getOnCommand(0));
            invoker.invoke(invoker.getOffCommand(0));
      //       invoker.undo();
            System.out.println("电视打开关闭操作===========");
            invoker.invoke(invoker.getOnCommand(1));
            invoker.undo();
        }
      }

  • 注意事项和细节 将发起请求的对象与执行请求的对象解耦 容易实现对请求的撤销和重做 空命令也是一种设计模式,它为我们省去了判空的操作

命令模式不足: 可能导致某些系统有过多的具体命令类,增加了系统的复杂度

与外观模式相似:都是将多个功能聚合在一起 外观模式更多适用于维护;命令模式更多应用于设计;

  • 应用 Spring框架中的JdbcTemplate类 容易设计一个命令队列。只要把命令对象放到列队,就可以多线程的执行命令 界面的一个按钮都是一条命令、模拟 CMD(DOS 命令)订单的撤销/恢复、触发- 反馈机制



over......


关键字:     设计模式  

备案号:湘ICP备19000029号

Copyright © 2018-2019 javaxl晓码阁 版权所有