• 命令模式的意图

  将一个请求封装成一个对象,从而使你可以用不同的请求对客户进行参数化;

  对请求排队或记录请求日志,以及支持可撤销的操作;

  命令模式告诉我们可以为一个操作生成一个对象并给出它的一个执行方法。





  • 命令模式的构成

  1.客户角色:

  创建一个具体命令对象,并确定其接受者。



  2.命令角色:

  声明一个给所有具体命令类的抽象接口。这是一个抽象角色,通常由一个接口或抽象类实现。



  3.具体命令角色:

  定义一个接收者和行为之间的弱耦合,实现execute方法,负责调用接收者的相应操作。



  4.请求者角色:

  负责调用命令对象执行请求。



  5.接收者角色:

  负责具体实施和执行一个请求。





关于命令者模式,我前面还有一篇博客。说的简单点命令者模式就是将请求对象和请求对象的实现解耦,2个都作为参数实现动态传参。在Java1.8中已经有了函数式接口,也就是专门针对Java不能将一段代码块作为参数传入一个方法做的补充。

OK,现在我们来写个例子吧。

package org.linkinpark.junit.testjunit;

/**
* @创建作者: LinkinPark
* @创建时间: 2016年2月5日
* @功能描述: 命令者模式接口
*/
public interface Command
{ void execute(); }

package org.linkinpark.junit.testjunit;

/**
* @创建作者: LinkinPark
* @创建时间: 2016年2月5日
* @功能描述: 接受者,也就是处理请求的那个对象
*/
public class Receiver
{ public void doSomething()
{
System.out.println("doSomething in receiver。。。");
} }
package org.linkinpark.junit.testjunit;

/**
* @创建作者: LinkinPark
* @创建时间: 2016年2月5日
* @功能描述: 接受者和行为之间的弱耦合实现
*/
public class ConcreteCommand implements Command
{ private Receiver receiver; public ConcreteCommand(Receiver receiver)
{
super();
this.receiver = receiver;
} @Override
public void execute()
{
receiver.doSomething();
} }
package org.linkinpark.junit.testjunit;

/**
* @创建作者: LinkinPark
* @创建时间: 2016年2月5日
* @功能描述: 请求执行器,创建一个请求接受者,然后触发命令者接口中对接受者行为的触发
*/
public class Invoker
{ private Command command; public Invoker(Command command)
{
super();
this.command = command;
} public void doAction()
{
command.execute();
} }
package org.linkinpark.junit.testjunit;

import org.junit.Test;

public class CommandTest
{ @Test
public void testCommand()
{
// 接收者
Receiver receiver = new Receiver(); // 命令:具体命令关联接收者
Command command = new ConcreteCommand(receiver); // 调用者
Invoker invoker = new Invoker(command); // 调用者调用命令,实际是所关联的接收者执行操作
invoker.doAction();
} }



OK,最后我们写了一个测试了,我们看下控制台,成功执行了我们想要的逻辑。

doSomething in receiver。。。

上面的这几段代码,轻松的实现了一个对象和该对象行为之间的松耦合。

1,假如我们现在想要改变该对象的行为,其他的代码根本不需要动。只需要修改command接口中对象的行为代码就OK。比如我们现在想在对象执行doSomething()方法前后执行特定的逻辑,直接这里修改就OK。比如我们现在对concreteCommand做如下修改:

package org.linkinpark.junit.testjunit;

/**
* @创建作者: LinkinPark
* @创建时间: 2016年2月5日
* @功能描述: 接受者和行为之间的弱耦合实现
*/
public class ConcreteCommand implements Command
{ private Receiver receiver; public ConcreteCommand(Receiver receiver)
{
super();
this.receiver = receiver;
} @Override
public void execute()
{
System.out.println("这里是对象执行doSomething()之前的行为。。。");
receiver.doSomething();
System.out.println("这里是对象执行doSomething()之后的行为。。。");
} }

控制台输出如下:

这里是对象执行doSomething()之前的行为。。。
doSomething in receiver。。。
这里是对象执行doSomething()之后的行为。。。

2,假如我们现在不想改变该对象的行为,而是想改变测试对象。那么我们只需要直接修改receiver对象就可以,比如我们继承或者重新组合一个对象。我们现在对Receiver对象派生一个子类:

package org.linkinpark.junit.testjunit;

public class SonReceiver extends Receiver
{ @Override
public void doSomething()
{
super.doSomething();
System.out.println("上面是父类的执行,这里开始走自己的逻辑。。。");
} }

控制台输出如下:

这里是对象执行doSomething()之前的行为。。。
doSomething in receiver。。。
上面是父类的执行,这里开始走自己的逻辑。。。
这里是对象执行doSomething()之后的行为。。。

在JUnit中的体现

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

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

使用命令(Command)模式后给系统的架构带来了哪些效果

  Command模式将实现请求的一方(TestCase)和调用一方(JUnit)进行解耦。

  Command模式使得新的TestCase很容易加入,无需改变已有的类,只需继承TestCase类即可,这样方便了测试人员。

  Command模式可以将多个TestCase进行组合成一个复合命令,TestSuite就是复合命令,它使用了Composite模式。

  Command模式容易把请求的TestCase组合成请求队列,这样使接收请求的一方(JUnit Framework)容易决定是否执行请求,一旦发现测试用例失败或者错误可以立刻停止,进行报告。





junit设计模式--命令者模式的更多相关文章

  1. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  2. linkin大话设计模式--命令模式

    linkin大话设计模式--命令模式 首先考虑一种应用情况,某个方法需要完成某一个功能,这个功能的大部分功能已经确定了,但是有可能少量的步骤没法确定,必须等到执行这个方法才可以确定. 也就是说,我们写 ...

  3. 【设计模式】Java设计模式 - 命令模式

    Java设计模式 - 命令模式 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目录 Ja ...

  4. Java设计模式-享元模式(Flyweight)

    享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用. FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查 ...

  5. 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)

    命令模式:游戏开发设计模式之命令模式(unity3d 示例实现) 对象池模式:游戏开发设计模式之对象池模式(unity3d 示例实现) 原型模式:游戏开发设计模式之原型模式 & unity3d ...

  6. 设计模式之迭代器模式详解(foreach的精髓)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 各位好,很久没以LZ的身份和 ...

  7. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

  8. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  9. iOS设计模式 - 命令

    iOS设计模式 - 命令 原理图 说明 命令对象封装了如何对目标执行指令的信息,因此客户端或调用者不必了解目标的任何细节,却仍可以对他执行任何已有的操作.通过把请求封装成对象,客户端可以把它参数化并置 ...

随机推荐

  1. Mac安装Scala

    1. 下载,解压Scala sdk,2. 配置环境变量(.bash_profile) SCALA_HOME="/Users/soft/scala_soft/scala-2.11.6" ...

  2. python之tuple

    1.python元组 Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. #创建元组 >>> tuple2 = 123,456,'hel ...

  3. CentOS配置SSH免密登录

    假如我们有两台CentOS机器,192.168.199.101,192.168.199.102,要想在101上远程连接102可以通过ssh命令来实现 ssh 192.168.199.102 如果没有配 ...

  4. 《JAVA程序设计与实例》记录与归纳--类与对象

    类与对象 概念贴士: 1. 类必须先定义了才能使用.类是创建对象的模板,创建对象也叫类的实例化. 2. 在Java中,使用new关键字来创建对象,一般有一下3个步骤: 1)声   明:声明一个对象,包 ...

  5. laravel ORM 命令2

    一.查询 获取数据库所有数据 Model::all() 获取指定条件数据 Modle::where('status','1')->get() 获取第一条数据 Model::where('stat ...

  6. top命令参数解析

    PID 进程ID USER 进程所有者的用户名 PR 任务优先级 NI nice值.数值越小表示优先级越高,数值越大表示优先越低. VIRT 进程使用的虚拟内存总量,单位kb.VIRT=SWAP+RE ...

  7. Machine Learning - week 3

    Classification 使用线性回归来分类,会很不准确.并且,它的范围也会超出 {0, 1}.所以使用下面的逻辑回归模型. Hypothesis representation 线性回归中 hθ( ...

  8. LightOJ1012-Guilty Prince-DFS

    Guilty Prince  Time Limit: 2 second(s) Memory Limit: 32 MB Once there was a king named Akbar. He had ...

  9. DFS+打表

    N皇后问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status ...

  10. kafka数据迁移实践

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:mikealzhou 本文重点介绍kafka的两类常见数据迁移方式:1.broker内部不同数据盘之间的分区数据迁移:2.不同broker ...