Apache commons chain 是什么

Apache common chain 是对责任链设计模式的改造封装,让使用者更加方便的使用。

简单回顾一下责任链设计模式

在阎宏博士的《JAVA与模式》一书中开头是这样描述责任链(Chain of Responsibility)模式的:

责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任

关键点:

链是一系列节点的集合

链的各个节点可随意拆分和组装

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。

责任链适用的场景

有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。

你想在不明确指定接受者的情况下,想过个对象中的一个提交一个请求。

可处理一个请求的对象集合应该被动态指定。

简单例子

abstract class Handler {

private Handler nextHandler;

public Handler getNextHandler() {

return nextHandler;

}

public void setNextHandler(Handler nextHandler) {

this.nextHandler = nextHandler;

}

public abstract void doHandler();

}

class ConcreteHandler extends Handler {

@Override

public void doHandler() {

if (getNextHandler() != null) {

System.out.println("还有责任链");

getNextHandler().doHandler();

} else {

System.out.println("我自己处理" + toString());

}

}

}

设计模式主体架构:

角色:

抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。 具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。 抽象处理者角色

public abstract class Handler {

/**

* 持有后继的责任对象

*/

protected Handler successor;

/**

* 示意处理请求的方法,虽然这个示意方法是没有传入参数的

* 但实际是可以传入参数的,根据具体需要来选择是否传递参数

*/

public abstract void handleRequest();

/**

* 取值方法

*/

public Handler getSuccessor() {

return successor;

}

/**

* 赋值方法,设置后继的责任对象

*/

public void setSuccessor(Handler successor) {

this.successor = successor;

}

}

具体处理者角色

public class ConcreteHandler extends Handler {

/**

* 处理方法,调用此方法处理请求

*/

@Override

public void handleRequest() {

/**

* 判断是否有后继的责任对象

* 如果有,就转发请求给后继的责任对象

* 如果没有,则处理请求

*/

if(getSuccessor() != null)

{

System.out.println("放过请求");

getSuccessor().handleRequest();

}else

{

System.out.println("处理请求");

}

}

}

客户端类:

public class Client {

public static void main(String[] args) {

//组装责任链

Handler handler1 = new ConcreteHandler();

Handler handler2 = new ConcreteHandler();

handler1.setSuccessor(handler2);

//提交请求

handler1.handleRequest();

}

}

Apache CommonsChain

CommonsChain实现了Chain of Responsebility和Command模式,其中的Catalog + 配置文件的方式使得调用方和Command的实现方的耦合度大大的降低,提高了灵活性。

如何使用

简单写了一个实现:

/**

*

Test implementation of Chain that exposes the

* getCommands() method publicy.

*/

public class TestChain extends ChainBase {

/**

* 获取责任链中所有加入的命令

* @return 责任链中的命令

*/

public Command[] getCommands() {

return (commands);

}

public static void main(String[] args) throws Exception {

TestChain testChain=new TestChain();

Context context=new ContextBase();

/**

* 加入执行命令1

*/

testChain.addCommand(new Command() {

public boolean execute(Context context) throws Exception {

System.out.println("执行命令1");

return false;

}

});

/**

* 加入执行命令2

* 注意:返回值为true 表示执行到此为止

*/

testChain.addCommand(new Command() {

public boolean execute(Context context) throws Exception {

System.out.println("执行命令2");

return true;

}

});

/**

* 加入执行命令3

*/

testChain.addCommand(new Command() {

public boolean execute(Context context) throws Exception {

System.out.println("执行命令3");

return false;

}

});

//执行链中的命令

testChain.execute(context);

//打印链中的所有命令

Command[] commands=testChain.getCommands();

for(Command command:commands){

System.out.println(command.getClass());

}

}

}

** 执行结果 **

- 执行命令1

- 执行命令2

- class org.apache.commons.chain.config.TestChain$1

- class org.apache.commons.chain.config.TestChain$2

- class org.apache.commons.chain.config.TestChain$3

基本对象

1. Command接口。它是Commons Chain中最重要的接口,表示在Chain中的具体某一步要执行的命令。它只有一个方法:boolean execute(Context context)。如果返回true,那么表示Chain的处理结束,Chain中的其他命令不会被调用;返回false,则Chain会继续调用下一个Command,直到:

[x] > Command返回true;

[x] > Command抛出异常;

[x] > Chain的末尾;

2. Context接口。它表示命令执行的上下文,在命令间实现共享信息的传递。Context接口的父接口是Map,ContextBase实现了Context。对于web环境,可以使用WebContext类及其子类(FacesWebContext、PortletWebContext和ServletWebContext)。

3. Chain接口。它表示“命令链”,要在其中执行的命令,需要先添加到Chain中。Chain的父接口是Command,ChainBase实现了它。

使用配置文件

test-config.xml

className="org.apache.commons.chain.impl.DelegatingCommand"/>

className="org.apache.commons.chain.impl.DelegatingCommand"/>

className="org.apache.commons.chain.impl.ExceptionCommand"/>

装入配置文件

public class ConfigParserTestCase extends TestCase {

private static final String DEFAULT_XML =

"/org/apache/commons/chain/config/test-config.xml";

// ------------------------------------------------------------ Constructors

/**

* Construct a new instance of this test case.

*

* @param name Name of the test case

*/

public ConfigParserTestCase(String name) {

super(name);

}

// ------------------------------------------------------ Instance Variables

/**

*

The Catalog to contain our configured commands.

*/

protected Catalog catalog = null;

/**

*

The Context to use for execution tests.

*/

protected Context context = null;

/**

*

The ConfigParser instance under test.

*/

protected ConfigParser parser = null;

// ---------------------------------------------------- Overall Test Methods

/**

* Set up instance variables required by this test case.

*/

public void setUp() {

catalog = new CatalogBase();

context = new ContextBase();

parser = new ConfigParser();

}

/**

* Return the tests included in this test suite.

*/

public static Test suite() {

return (new TestSuite(ConfigParserTestCase.class));

}

/**

* Tear down instance variables required by this test case.

*/

public void tearDown() {

parser = null;

context = null;

catalog = null;

}

/**

执行测试方法

**/

public void testExecute2c() throws Exception {

load(DEFAULT_XML);

try {

catalog.getCommand("Execute").execute(context);

} catch (ArithmeticException e) {

assertEquals("Correct exception id",

"3", e.getMessage());

}

checkExecuteLog("1/2/3");

}

/**

从配置文件中加载配置信息

**/

protected void load(String path) throws Exception {

parser.parse(this.getClass().getResource(path));

catalog = CatalogFactoryBase.getInstance().getCatalog();

}

}

注意:使用配置文件的话,需要使用Commons Digester。而Digester则依赖:Commons Collections、Commons Logging和Commons BeanUtils。

4. Filter接口。它的父接口是Command,它是一种特殊的Command。除了Command的execute,它还包括一个方法:boolean postprocess(Context context, Exception exception)。Commons Chain会在执行了Filter的execute方法之后,执行postprocess(不论Chain以何种方式结束)。Filter的执行execute的顺序与Filter出现在Chain中出现的位置一致,但是执行postprocess顺序与之相反。如:如果连续定义了filter1和filter2,那么execute的执行顺序是:filter1 -> filter2;而postprocess的执行顺序是:filter2 -> filter1。

5. Catalog接口。它是逻辑命名的Chain和Command集合。通过使用它,Command的调用者不需要了解具体实现Command的类名,只需要通过名字就可以获取所需要的Command实例。

6.

的使用。配置文件的引入,使得Commons Chain的灵活性大大的提高。在实际的使用过程中,存在着同一个Command被多个Chain使用的情形。如果每次都书写Command的类名,尤其是前面的包名特别长的情况下,是非常枯燥的。而

的作用就是为了解决这样的麻烦。通过定义Command和Chain的别名,来简化书写。配置文件,可以书写成:

className="org.apache.commons.chain.generic.LookupCommand"/>

参考:

java commons-chain_Apache commons chain 初探相关推荐

  1. java 8中 predicate chain的使用

    文章目录 简介 基本使用 使用多个Filter 使用复合Predicate 组合Predicate Predicate的集合操作 总结 java 8中 predicate chain的使用 简介 Pr ...

  2. java apache commons_Apache commons(Java常用工具包)简介

    Apache Commons是一个非常有用的工具包,解决各种实际的通用问题,下面是一个简述表,详细信息访问http://jakarta.apache.org/commons/index.html Be ...

  3. <Java>使用commons.io修改文件内容(中文标点符号改成英文)

    一.前言 今天整理笔记,发生笔记中很多代码和笔记的标点符号是中文符号,所以写了个很简单的代码实现中文标点符号改成英文标点符号,读写文件涉及到io流,传统io流使用起来不是很方便,代码量多,难记!(赶时 ...

  4. java 用Apache Commons Email发邮件

    所需jar包:commons-email-1.4.jar和mail-1.4.1jar SimpleEmail 用于发送普通文本邮件 package liu.email;import org.apach ...

  5. java dochain,Java filter中的chain.doFilter详解

    转载: 一.chain.doFilter作用 1.一般filter都是一个链,web.xml 里面配置了几个就有几个.一个一个的连在一起 request -> filter1 -> fil ...

  6. Java filter中的chain.doFilter详解

    一.chain.doFilter作用 1.一般filter都是一个链,web.xml 里面配置了几个就有几个.一个一个的连在一起 request -> filter1 -> filter2 ...

  7. java游侠_Java Lambda表达式初探

    Java Lambda表达式初探 前言 Java 8已经发行两年多,但很多人仍然在使用JDK7.对企业来说,技术上谨慎未必是坏事,但对个人学习而言,不去学习新技术就很可能被技术抛弃.Java 8一个重 ...

  8. java多线程之API初探(一)

    线程创建有两种方式:  1.实现runnable接口  2.继承thread 线程   都重写run方法 2.runnable接口优势: java 单继承但可以实现多个接口 runnable 方式可以 ...

  9. Java笔记14:泛型初探

    一.泛型简介 泛型是从Java SE 1.5开始出现的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛 ...

最新文章

  1. gRPC amp; Protocol Buffer 构建高性能接口实践
  2. idea启动tomcat时蓝屏
  3. 经典数据结构——堆的实现
  4. 【java】两个线程如何交替执行,一个输出偶数一个输出奇数?
  5. CS 系统框架二[增加默认启动以及代码打开窗体]
  6. 使用WSDL工具生成C#使用的WebService声明文件
  7. 在MongoDB中实现聚合函数
  8. NGFF(M.2) m.2中Bkey接口Mkey接口有什么不同
  9. Vivado2017.4软件安装
  10. 苹果手机怎么投屏不了,苹果手机怎么投屏电脑
  11. ios开发学习--按钮(Button)效果源码分享
  12. 关于微信小程序自定义交易组件升级处理的相关问题,及解决思路
  13. 滴滴校招 餐馆最大收益问题
  14. VUE-table表格操作列表适配屏幕缩小固定右侧fixed
  15. 公司注册的种类及英文缩写
  16. 关于随机森林randomforest对结果进行分类的原则的个人理解
  17. App前端,Web前端,后端,微信小程序到底该学啥?
  18. html+css+JavaScript实现导航栏
  19. 基于单目视觉的同时定位与地图构建方法综述
  20. 线下空间体验如何承载商业策略——从宜家的冰淇淋说起

热门文章

  1. “苹果光环”褪色后,瑞声靠什么坐稳头把交椅?
  2. “抢滩”中高端酒店,新老玩家谁会更先跑出来?
  3. java 随机数 分布_java – 随机数的分布
  4. linux grub设置cpu频率,Linux:使用性能调控器时,为什么CPU频率会发生波动?
  5. 联想台式计算机设置双层密码,联想电脑怎样设密码?联想电脑设置密码方法步骤【图文】...
  6. Python面向对象的三大特性
  7. python格式化输出的三种形式
  8. wandb(wb)(weights and biases): 深度学习轻量级可视化工具入门教程
  9. 【AITISA 第11次标准会议新一代人工智能产业技术创新战略联盟——AI标准工作组】神经网络压缩组会议
  10. 【中级软考】前驱图是什么?(貌似又名“前趋图”)