• 大话设计模式读书笔记(命令模式)


    人物:大鸟,小菜

    事件:小菜和大鸟去吃烧烤,发现路边的烧烤摊人多拥挤,老板在烤肉的同时可能记不住点菜人的名字,导致给错,没收钱,没烤熟等一系列问题,而且白天有城管,晚上太晚人们也不愿意吃路边摊,这些都导致了路边烧烤摊赚钱不稳定,而有店面的烧烤店,虽然要交一定的租金,但是没了哪些不稳定因素,收入就相对稳定了,大鸟就烧烤店好过烧烤摊这个情景,引出了命令模式。


    命令模式:

    1.借烤肉事件设计代码,初次设计为紧耦合设计

    2.在明确紧耦合设计的不好点后,又进行了松耦合设计

    3.进一步完善松耦合设计

    4.最后借上述例子引出命令模式并阐述了优点

    紧耦合设计

    趁着烤串还没出来,大鸟让小菜设计实现烧烤摊营业模式

    Barbecuer类,路边烤肉实现:

    @Slf4j
    public class Barbecuer {
        public void BakeMutton() {
            log.info("烤羊肉串");
        }
    
        public void BakeChickenWing() {
            log.info("烤鸡翅!");
        }
    }

    客户端:

    public class BarbecueClient {
        public static void main(String[] args) {
            Barbecuer boy = new Barbecuer();
            boy.BakeMutton();
            boy.BakeMutton();
            boy.BakeMutton();
            boy.BakeChickenWing();
            boy.BakeMutton();
            boy.BakeMutton();
            boy.BakeChickenWing();
        }
    }

    大鸟:这样人一多,请求一多久容易乱,你再试试烧烤店营业模式

    松耦合设计

    代码结构图:

    Command类,即抽象命令类:

    public abstract class Command {
        protected Barbecuer receiver;
    
        public Command(Barbecuer receiver) {
            this.receiver = receiver;
        }
    
        abstract public void excuteCommand();
    }

    烤羊肉串,即具体命令类:

    public class BakeMuttonCommand extends Command {
        public BakeMuttonCommand(Barbecuer receiver) {
            super(receiver);
        }
    
        @Override
        public void excuteCommand() {
            receiver.BakeMutton();
        }
    }

    烤鸡翅,即具体命令类:

    public class BakeChickenWingCommand extends Command {
        public BakeChickenWingCommand(Barbecuer receiver) {
            super(receiver);
        }
    
        @Override
        public void excuteCommand() {
            receiver.BakeChickenWing();
        }
    }

    Waiter类,即服务员类:

    public class Waiter {
        private Command command;
    
        public void setCommand(Command command) {
            this.command = command;
        }
    
        public void notifyCook() {
            command.excuteCommand();
        }
    }

    客户端代码:

    public class BarbecueClient {
        public static void main(String[] args) {
            //开店前的准备
            Barbecuer boy = new Barbecuer();
            Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
            Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
            Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
            Waiter girl = new Waiter();
    
            //开门营业
            girl.setCommand(bakeMuttonCommand1);
            girl.notifyCook();
            girl.setCommand(bakeMuttonCommand2);
            girl.notifyCook();
            girl.setCommand(bakeChickenWingCommand1);
            girl.notifyCook();
        }
    }

    大鸟:不错,功能基本实现了,但是和实际场景有点不符合,因为一般叫烤串是一次叫6串,而不是一串一串叫叫6次,还有就是客户也不知道到底有没有卖完,最后就是客户点了哪些食物饮料,都是需要记录的,不然人一多,就忘了。

    松耦合的进一步优化

    小菜进行了第三版编写:

    服务员类:

    @Slf4j
    public class Waiter {
        private List<Command> orders = new ArrayList<>();
    
        /**
         * 设置订单
         *
         * @param command
         */
        public void setOrder(Command command) {
            if (command.getClass().getName().equalsIgnoreCase("com.example.pmingup.service.designModeWan.BakeChickenWingCommand")) {
                log.info("服务员,鸡翅没有了,请点别的烧烤");
            } else {
                orders.add(command);
                log.info("增加订单:" + command.getClass().getName() + "事件: " + new Date());
            }
        }
    
        /**
         * 取消订单
         *
         * @param command
         */
        public void cancelOrder(Command command) {
            orders.remove(command);
            log.info("取消订单:" + command.toString() + "事件:" + new Date());
        }
    
        /**
         * 通知全部执行
         */
        public void notifyCook() {
            for (Command cd : orders) {
                cd.excuteCommand();
            }
        }
    }

    客户端代码:

    public class BarbecueClient {
        public static void main(String[] args) {
            //开店前的准备
            Barbecuer boy = new Barbecuer();
            Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
            Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
            Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
            Waiter girl = new Waiter();
    
            //开门营业
           girl.setOrder(bakeMuttonCommand1);
           girl.setOrder(bakeMuttonCommand2);
           girl.setOrder(bakeChickenWingCommand1);
    
           girl.notifyCook();
        }
    }

    命令模式

    1.概念:将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

    2.结构图:

    3.代码如下:

    CommandDemo类,来声明执行操作的接口:

    public abstract class CommandDemo {
        protected Receiver reciever;
    
        public CommandDemo(Receiver reciever) {
            this.reciever = reciever;
        }
    
        abstract public void execute();
    }

    ConcreteCommand类,将一个接受者对象绑定一个动作,调用接受者相应的操作,以实现execute():

    public class ConcreteCommand extends CommandDemo {
        public ConcreteCommand(Receiver reciever) {
            super(reciever);
        }
    
        @Override
        public void execute() {
            reciever.action();
        }
    }

    Invoker类,要求该命令执行这个请求:

    public class Invoker {
        private CommandDemo commandDemo;
    
        public void setCommandDemo(CommandDemo commandDemo) {
            this.commandDemo = commandDemo;
        }
    
        public void executeCommand() {
            commandDemo.execute();
        }
    }

    Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接受者:

    @Slf4j
    public class Receiver {
        public void action() {
            log.info("执行请求!");
        }
    }

    客户端代码:

    public class BarbecueClient {
        public static void main(String[] args) {
            Receiver r = new Receiver();
            CommandDemo c = new ConcreteCommand(r);
            Invoker i = new Invoker();
            i.setCommandDemo(c);
            i.executeCommand();
        }
    }

    4.优点:

    (1)能较容易地设计一个命令队列

    (2)需要时,能较容易地将命令记入日志

    (3)允许接收请求的一方决定是否要求否决请求

    (4)容易实现对请求的撤销和重做

    (5)新加的命令不会影响其他类,因此增加新的命令很容易

    (6)命令模式把请求一个操作的对象与知道怎么执行操作的一个对象分割开来

  • 相关阅读:
    虚方法、重写方法以及抽象类的知识小结
    DateTime时间格式
    JavaScript中Eval()函数的作用
    JQuery Event属性说明
    正则表达式30分钟入门教程
    dwz的form表单中url的变量替换
    dwz中权限的控制
    Dwz下拉菜单的二级联动
    Win7下用IIS发布网站
    IntelliJ IDEA 常用快捷键列表及技巧大全
  • 原文地址:https://www.cnblogs.com/wencheng9012/p/13448069.html
Copyright © 2020-2023  润新知