有两种情况可运用链式方法:

第一种  除最后一个方法外,每个方法都返回一个对象

object2 = object1.method1();

object3 = object2.method2();

object3.method3();

以上三行代码等价于如下链式方法

object1.method1().method2().method3();

第二种 调用同一个对象的多个方法

user.setName(String name);

user.setPassword(String password);

user.setRole(String role);

以上三行代码等价于如下链式方法

user

.setName(String name)

.setPassword(String password)

.setRole(String role);

示例:

使用chaining:

package com.dxz.base;

public class Persion {
private int id;
private String name;
private String phoneNumber;
private String address; public Persion() { } public Persion setId(int id) {
this.id = id;
return this;
}
public Persion setName(String name) {
this.name = name;
return this;
}
public Persion setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public Persion setAddress(String address) {
this.address = address;
return this;
}
public Persion printId() {
System.out.println(this.id);
return this;
}
public Persion printName() {
System.out.println(this.name);
return this;
}
public Persion printPhoneNumber() {
System.out.println(this.phoneNumber);
return this;
}
public Persion printAddress() {
System.out.println(this.address);
return this;
}
}
package com.dxz.base;

public class Test {
public static void main(String[] args) {
/*Persion persion1 = new Persion();
persion1.setId(3);
persion1.setName("John");
persion1.setPhoneNumber("1111111");
persion1.setAddress("US");
persion1.printId();
persion1.printName();
persion1.printPhoneNumber();
persion1.printAddress();*/
Persion persion1 = new Persion();
persion1.setId(3).setName("John")
.setPhoneNumber("1111111").setAddress("US");
persion1.printId()
.printName()
.printPhoneNumber()
.printAddress();
}
}

结果:

3
John
1111111
US

直到前一段开始看老马的《特定领域语言》这本书才知道这种用法是一种DSL,老马还给他起了一个名字 连贯接口(fluent interface)。

关于DSL,它最大的用处就是:将常见模式抽取出来,使之变成更加有可读性的描述方式。是的!有好的可读性:你之所以觉得正则表达式(另一种DSL)比一堆String解析代码难读,是你没有付出学习正则表达式的时间。当你掌握了一种DSL的规则后,你会觉得它更简便,更具有可读性,你要付出的是学习成本,而带来的则是效率的提高,与眼前的清爽。

上面的3个例子中,我们发现阅读更加简便,代码量也减少了很多。那么它是如何实现的呢?其实很简单,你可以把它看做是一种责任链模式的简写/变种。我们看一段示例代码,这段代码中,创建了一个AppoinetmentCalendarChained 的实例calendar。对calendar进行了链式操作:add().from().to().at()

public class CalendarDemoChained {

    public static void main(String[] args) {
new CalendarDemoChained();
} public CalendarDemoChained() {
Calendar fourPM = Calendar.getInstance();
fourPM.set(Calendar.HOUR_OF_DAY, 16);
Calendar fivePM = Calendar.getInstance();
fivePM.set(Calendar.HOUR_OF_DAY, 17); AppointmentCalendarChained calendar =
new AppointmentCalendarChained();
calendar.add("dentist").
from(fourPM).
to(fivePM).
at("123 main street"); calendar.add("birthday party").at(fourPM);
displayAppointments(calendar);
} private void displayAppointments(AppointmentCalendarChained calendar) {
for (Appointment a : calendar.getAppointments())
System.out.println(a.toString());
}
}

实现链式操作的类

public class Appointment {
private String _name;
private String _location;
private Calendar _startTime;
private Calendar _endTime; public Appointment(String name) {
this._name = name;
} public Appointment() {
} public Appointment name(String name) {
_name = name;
return this;
}
public Appointment at(String location) {
_location = location;
return this;
} public Appointment at(Calendar startTime) {
_startTime = startTime;
return this;
} public Appointment from(Calendar startTime) {
_startTime = startTime;
return this;
} public Appointment to(Calendar endTime) {
_endTime = endTime;
return this;
} public String toString() {
return "Appointment:"+ _name +
((_location != null && _location.length() > 0) ?
", location:" + _location : "") +
", Start time:" + _startTime.get(Calendar.HOUR_OF_DAY) +
(_endTime != null? ", End time: " +
_endTime.get(Calendar.HOUR_OF_DAY) : "");
}
}

我们来看add from to 这些方法。每个方法调用后都把实例本身返回了进去,java支持匿名调用,这样就可以直接调用自身方法了,其实挺简单的。

当链式操作有顺序的时候(如某些操作必须有一些前置操作),就要多封装一些复杂逻辑了,老马的书里有很多丰富的思路介绍(第10,11,33,38,50章),但并不是非常详细,需要自己再拓展阅读。

btw,要多说2句的是,连贯接口只是DSL的一种,2个常见的测试相关框架已经在大量使用了。去年用的较多的Robotframework 使用的关键字驱动也是一种典型的DSL。多学习抽象的方法对自动化框架的设计应该说有很大好处。

参考书籍:《特定领域语言》

参考链接:

1.http://martinfowler.com/bliki/FluentInterface.html

2.http://www.ibm.com/developerworks/cn/java/j-eaed13/

3.http://jmock.org/oopsla2006.pdf

Java链式方法 连贯接口(fluent interface)的更多相关文章

  1. Java链式方法

    http://blog.csdn.net/lemon_shenzhen/article/details/6358537 有两种情况可运用链式方法: 第一种  除最后一个方法外,每个方法都返回一个对象 ...

  2. 简谈 JavaScript、Java 中链式方法调用大致实现原理

    相信,在 JavaScript .C# 中都见过不少链式方法调用,那么,其中实现该类链式调用原理,大家有没有仔细思考过?其中 JavaScript 类库:jQuery 中就存在大量例子,而在 C# 中 ...

  3. C#用链式方法表达循环嵌套

    情节故事得有情节,不喜欢情节的朋友可看第1版代码,然后直接跳至“三.想要链式写法” 一.起缘 故事缘于一位朋友的一道题: 朋友四人玩LOL游戏.第一局,分别选择位置:中单,上单,ADC,辅助:第二局新 ...

  4. JAVA的核心概念:接口(interface)

    JAVA的核心概念:接口(interface) 接口与类属于同一层次,实际上,接口是一种特殊的抽象类. 如:    interface IA{ }  public interface: 公开接口  与 ...

  5. Java 链式编程

    这里来做一个Java 链式编程的例子,基本就是每次返回一个对象本身,这样就能够去调用对象的方法和属性. package com.sun; public class Demo05 { /** * @pa ...

  6. C#用链式方法

    C#用链式方法表达循环嵌套   情节故事得有情节,不喜欢情节的朋友可看第1版代码,然后直接跳至“三.想要链式写法” 一.起缘 故事缘于一位朋友的一道题: 朋友四人玩LOL游戏.第一局,分别选择位置:中 ...

  7. Java 链式写法

    Java链式写法,子类继承父类的属性,也可以返回子类的对象,只是需要重写基类的Set方法 public class MyLS { public static void main(String[] ar ...

  8. C#中扩展StringBuilder支持链式方法

    本篇体验扩展StringBuilder使之支持链式方法. 这里有一个根据键值集合生成select元素的方法. private static string BuilderSelectBox(IDicti ...

  9. Java链式写法

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11613067.html Java 链式写法:详细看代码 package chain; /** ...

随机推荐

  1. 另一个分区工具GNU的parted[转自vbird]

    利用 GNU 的 parted 进行分割行为 虽然你可以使用 fdisk 很快速的将你的分割槽切割妥当,不过 fdisk 却无法支持到高于 2TB 以上的分割槽! 此时就得需要 parted 来处理了 ...

  2. 查找目录下的所有文件中是否含有某个字符串 linux

    查找目录下的所有文件中是否含有某个字符串 find .|xargs grep -ri "IBM" 查找目录下的所有文件中是否含有某个字符串,并且只打印出文件名 find .|xar ...

  3. python文件操作--字符串替换

    如把test.txt文件的 所有 AAA 字符串 替换成 aaaaa with open('test.txt','+r') as f: t = f.read() t = d.replace('AAA' ...

  4. dll--二进制层面的复用

    积木式思想其实是很自然的一个过程,从c的库函数到C++的标准库,再到dll.com.com+都是这种思想推动下的结果,和现实生活中的人们的思维方式并无二致,只不过软件是在一个虚拟的世界中,并分化出许多 ...

  5. page cache 与 page buffer 转

    page cache 与 page buffer 标签: cachebuffer磁盘treelinux脚本 2012-05-07 20:47 2905人阅读 评论(0) 收藏 举报  分类: 内核编程 ...

  6. threading模块和queue模块实现程序并发功能和消息队列

    简介: 通过三个例子熟悉一下python threading模块和queue模块实现程序并发功能和消息队列. 说明:以下实验基于python2.6 基本概念 什么是进程? 拥有独立的地址空间,内存,数 ...

  7. 发现PDF Transformer+转换的图像字体小了如何处理

    ABBYY PDF Transformer+转换的原始图像字体太小怎么办?为了获得最佳文本识别效果,请用较高的分辨率扫描用极小字体打印的文档,否则很容易在转换识别时出错.下面小编就给大家讲讲该怎么解决 ...

  8. OCR文字识别软件许可文件被误删了怎么办

    使用任何一款软件,都会有误操作的情况发生,比如清理文件时一不小心删除了许可文件,对于ABBYY FineReader 12这样一款OCR文字识别软件,因失误错误删除了许可文件该怎么办呢?今天就来给大家 ...

  9. unity, 搜索组件

    Hierarchy的搜索栏中既可以搜节点名,也可以搜组件名.

  10. 【转】asp.net导出数据到Excel的三种方法

    来源:http://www.cnblogs.com/lishengpeng1982/archive/2008/04/03/1135490.html 原文出处:http://blog.csdn.net/ ...