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

我回来啦!今天是周六,一看命令模式还有一个总结未完成,赶忙爬起来作作好。java

就如上一篇所说的,若是拥有了一个遥控器,却没法光凭按下一个按你,就同时能弄暗灯光、打开音响和电视、设置到DVD,并让热水器开始加温,那么我要这个遥控器还有什么意义呢?编程

使用宏命令

根据比较高级的想法来看,就是咱们须要制造一种新的命令,用来执行其余一堆命令,而不仅是执行一个命令,这样就是一个不错的想法了吧。这就是咱们将要说的宏命令。数组

public class MacroCommand implements Command {
    // 在宏命令中,用命令数组存储一大堆命令
    Command[] commands;
 
    public MacroCommand(Command[] commands) {
        this.commands = commands;
    }
 
    public void execute() {
        for (int i = 0; i < commands.length; i++) {
        // 当这个宏命令被遥控器执行时,就一次性执行数组里的每一个命令
            commands[i].execute();
        }
    }
 
    /**
     * NOTE:  these commands have to be done backwards to ensure 
     * proper undo functionality
     */
    public void undo() {
        for (int i = commands.length -1; i >= 0; i--) {
            commands[i].undo();
        }
    }
}

让咱们来看下如何使用宏命令:网络

  1. 先建立想要进入宏的命令集合
Light light = new Light("Living Room");
TV tv = new TV("Living Room");
Stereo stereo = new Stereo("Living Room");
Hottub hottub = new Hottub();
 
LightOnCommand lightOn = new LightOnCommand(light);
StereoOnCommand stereoOn = new StereoOnCommand(stereo);
TVOnCommand tvOn = new TVOnCommand(tv);
HottubOnCommand hottubOn = new HottubOnCommand(hottub);
  1. 接下来建立两个数组,其中一个用来记录开启命令,另外一个用来记录关闭命令,并在数组内放入对应的命令
Command[] partyOn = { lightOn, stereoOn, tvOn, hottubOn};
Command[] partyOff = { lightOff, stereoOff, tvOff, hottubOff};
  
MacroCommand partyOnMacro = new MacroCommand(partyOn);
MacroCommand partyOffMacro = new MacroCommand(partyOff);
  1. 而后将宏命令指定给咱们所但愿的按钮:
remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
  1. 最后,只需按下一些按钮,测试是否正常工做
System.out.println(remoteControl);
System.out.println("--- Pushing Macro On---");
remoteControl.onButtonWasPushed(0);
System.out.println("--- Pushing Macro Off---");
remoteControl.offButtonWasPushed(0);

不会忘记咱们的撤销功能数据结构

public void undo() {
    for (int i = commands.length -1; i >= 0; i--) {
        commands[i].undo();
    }
}

命令模式的更多用途:队列请求

命令能够将运算块打包(一个接收者和一组动做),而后将它传来传去,就像是通常的对象同样。如今,即便在命令被建立许久以后,运算依然能够被调用。事实上,它甚至能够在不一样的线程中被调用。咱们能够利用这样的特性衍生一些应用,例如:日程安排、线程池、工做队列等。框架

想象一个工做队列:你再某一端添加命令,而后另外一端则是线程。线程进行下面的动做:从队列中取出一个命令,调用它的execute()方法,等待这个调用完成,而后将此命令对象丢弃,再取出下一个命令。。。工具

请注意,工做队列类和进行计算的对象之间彻底是解耦的。此刻线程可能在进行财务运算,下一刻却在读取网络数据。工做队列对象不在意到底作些什么,他们只知道取出命令对象,而后调用其execute()方法。学习

命令模式的更多用途:日志请求

某些应用须要咱们将全部的动做都记录在日志中,并能在系统死机以后,从新调用这些动做恢复到以前的状态。命令模式可以支持这一点。测试

当咱们执行命令的时候,将历史记录存储在磁盘中,一旦系统死机,咱们就能够将命令对象从新加载,并成批地依次调用这些对象的execute()方法。this

好比有许多调用大型数据结构的应用没法在每次改变发生时被快速地存储。经过使用记录日志,咱们能够将上次检查点以后的全部操做记录下来,若是系统出情况,从检查点开始应用这些操做。好比说,对于电子表格应用,咱们可能想要实现的错误回复方式是将电子表格的操做记录在日志中,而不是每次电子表格一有变化就记录整个电子表格。

对于更高级的应用而言,这些技巧能够被扩展应用到事务处理中,也就是说,一整群操做必须所有进行完成,或者没有进行任何的操做

设计箱内的工具

仍是按照以前的套路,总结下工具箱内新增的工具吧

  • OO基础

    抽象、封装、继承、多态

  • OO原则

    封装变化

    多用组合,少用继承

    针对接口编程,不针对实现编程

    为交互对象之间的松耦合设计而努力

    依赖抽象,不要依赖具体类

    类应该对扩展开放,对修改关闭

  • OO模式

    『策略模式』、『观察者模式』、『装饰者模式』、『抽象工厂模式』、『工厂方法模式』、『单例模式』

    命令模式』将请求封装成对象,这可让你使用不一样的请求、队列,或者日志请求来参数化其余对象。命令模式也能够支持撤销操做。

咱们学习命令模式,就是一个按部就班的过程,先从简单的开关开始,而后再到复杂的开启状态,进而想到队列,想到记录日志这种事务操做。学习也是一个按部就班的过程,咱们经过简单的Demo学习,而后到项目实践,再到后面独立设计框架,我相信你们都能悟出这个道理来。

持续学习,精进学习,咱们会一块儿加油。下一次,咱们将学习适配器模式与外观模式

爱生活,爱学习,爱感悟,爱挨踢

相关文章
相关标签/搜索