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

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

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. 万能写入sql语句,并且防注入

    通过perpare()方法和检查字段防sql注入. $pdo=new PDO('mysql:host=localhost;dbname=scms', 'root' ); $_POST=array('t ...

  2. 关于CPU Cache -- 程序猿需要知道的那些事

    本文将介绍一些作为程序猿或者IT从业者应该知道的CPU Cache相关的知识 文章欢迎转载,但转载时请保留本段文字,并置于文章的顶部 作者:卢钧轶(cenalulu) 本文原文地址:http://ce ...

  3. asp.net MVC 自定义@helper 和自定义函数@functions小结

    asp.net Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的切换,大大提升了我们的开发效率.但是Razor语法还是有一些棉花糖值得我们了解一下,可以更加强劲的提升我们 ...

  4. 022. ASP.NET为DataSet中数据集添加关系及动态创建主子表和添加主子表关系

    protected void Page_Load(object sender, EventArgs e) { string connectionString = "server=.;data ...

  5. 关于malloc申请的动态内存的问题

    http://bbs.bccn.net/thread-331344-1-1.html #include<stdio.h>#include<stdlib.h>int main(v ...

  6. OpenJudge计算概论-单词排序

    /*===================================== 单词排序 总时间限制:1000ms 内存限制: 65536kB 描述 输入一行单词序列,相邻单词之间由1个或多个空格间隔 ...

  7. no ocijdbc11 in java.library.path linux

    no ocijdbc11 in java.library.path linux vi /etc/profile export ORACLE_HOME=/oracle/database/oracle/p ...

  8. Keepalived+MySQL实现高可用(转)

    http://www.cnblogs.com/wingsless/p/4033093.html   MHA高可用 http://www.cnblogs.com/gomysql/p/3856484.ht ...

  9. java mail使用中遇到的550类型错误

    前言 首先,需要说明的是,本错误来自于一个简单的基于java mail的api程序,邮件服务器是163的SMTP,即smtp.163.com. 程序 需要说明一下,下面这个程序,是来自于网络上,本人为 ...

  10. [转]wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容)

    首先说几个最常用的关键字,“eq” 和 “==”等同,可以使用 “and” 表示并且,“or”表示或者.“!" 和 "not” 都表示取反. 一.针对wireshark最常用的自然 ...