程序员想法

Junit中的命令模式

2019-02-25  本文已影响123人  碧鬼鸠

Junit中的命令模式

目录

命令模式介绍

命令模式定义

命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。
命令模式也支持可撤销的操作。
命令对象将动作和接收者包进对象中。

命令模式的类图

命令模式类图.png

命令模式实现遥控器的类图

命令模式实现遥控器的类图.png

撤销操作的实现

在Command接口中加入undo()方法,然后每个具体的命令类都实现这个方法:undo方法中调用的操作和execute()方法中的操作相反,比如on的反面是off。
遥控器类也要做一些修改:加入新的实例变量记录上一个操作,当按下撤销按钮,就调用该实例变量的undo()方法。
如果撤销到某一个状态需要记录一些变量值,则在execute()方法中加入保存操作前状态数值的语句,然后在undo()的时候恢复。
如果想要多次撤销,即撤销到很早以前的状态,可以使用一个堆栈记录操作过程的每一个命令。

宏命令

通过一个键,控制多种操作。
在宏命令中,用命令数组存储一大堆命令,当这个宏命令被遥控器执行时,就一次性执行数组里的每个命令。

命令模式的应用——队列请求

命令可以将运算块打包(一个接收者和一组动作),然后将它传来传去,就像是对一般的对象一样。
我们可以利用这样的特性衍生一些应用,例如:日程安排,线程池,工作队列等想象有一个工作队列:你在一端添加命令,然后另一端则是线程。
线程从队列中取出命令,调用它的execute()方法,等待这个调用完成,然后将此命令对象丢弃,再取出下一个命令……

命令模式的应用——日志请求

某些应用需要我们将所有的动作都记录在日志中,并能在系统死机之后,重新调用这些动作恢复到之前的状态。
通过新增两个方法store()、load(),命令模式就能够支持这一点。
在Java中,我们可以利用对象的序列化(Serialization)实现这些方法,但是一般认为序列化最好还是只用在对象的持久化上(persistence)。
怎么做:当我们执行命令的时候,将历史记录储存在磁盘中。一旦系统死机,我们就可以将命令对象重新加载,并成批地依次调用这些对象的execute()方法。

命令模式构成

1.客户角色:
创建一个具体命令对象,并确定其接收者。
2.命令角色:
声明一个给所有具体命令类的抽象接口。这是一个抽象角色,通常由一个接口或抽象类实现。
3.具体命令角色:
定义一个接收者和行为之间的弱耦合,实现execute方法,负责调用接收者的相应操作。
4.请求者角色:
负责调用命令对象执行请求。
5.接收者角色:
负责具体实施和执行一个请求。

代码实例

一个简单的代码例子,实现命令模式中的各个角色

接收者

//接收者
public class Receiver{
    public void doAction(){
        System.out.println("doAction in Receiver");
     }
}

抽象的命令角色

//抽象的命令角色
public interface Command{
    public void execute();
}

具体的命令角色

//具体的命令角色,关联到一个接收者
public class ConcreteCommand implements Command{
    private Receiver receiver; 
    public ConcreteCommand(Receiver receiver){ 
        this.receiver = receiver;
    }
    
    @Override public void execute(){ 
        //负责调用接收者的相应操作
        receiver.doAction();
    }
}

命令调用者

//命令调用者,请求者
public class Invoker{ 
    private Command command; public Invoker(Command command){            
        this.command = command;
    } 
    public void doInvokerAction(){ 
        // 负责调用命令对象执行请求
        command.execute();
    }
}

客户角色

public class Client{ 
public static void main(String[] args){ 
    // 接收者
    Receiver receiver = new Receiver(); // 命令:具体命令关联接收者
    Command command = new ConcreteCommand(receiver); // 调用者
    Invoker invoker = new Invoker(command); // 调用者调用命令,实际是所关联的接收者执行操作
    invoker.doInvokerAction();
    }
}

Junit中的体现

我们编写的TestCase就像是一个命令,通过调用器调用后,JUnit框架中有相应的接收者来执行我们的测试方法。TestCase是真正的测试执行者,每个测试用例都会生成一个TestCase对象,这就是典型的命令者模式。TestCase实现Test接口中定义的方法,测试开发人员只需要关注这些接口方法,而不必关心TestCase以及junit内部的实现细节,run()方法就是Command模式中Execute()方法。

public void run(TestResult result){  
    result.run(this);  
}

优点

缺点

由于命令模式只能为一个操作(方法)生成一个对象并给出它的一个"execute(执行)"方法。所以10个操作就要生成10个对象。而且每个类中只能有一个方法,然后由接收者去执行这个方法。

上一篇下一篇

猜你喜欢

热点阅读