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

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

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. rac ASM下最简单归档开启方法

    原创作品,出自 "深蓝的blog" 博客,深蓝的blog:http://blog.csdn.net/huangyanlong/article/details/47172639本次先 ...

  2. RxJava + Retrofit 的实际应用场景

    关于 RxJava Retrofit 很多篇文章都有详细的说明,在这里我想分享一个具体的使用案例,在我的开源项目 就看天气 里的实际应用.也希望跟大家探讨如何优雅的使用. 准备 项目中用到的依赖: c ...

  3. CSS中:display:none与visible:hidden的区别

    display:none视为不存在且不加载,即,不为被隐藏的对象保留其物理空间,即该对象在页面上彻底消失. visibility:hidden隐藏,但在浏览时保留位置,即,使对象在网页上不可见,但该对 ...

  4. 使用JavaScript实现一个倒数计时程序

    使用JavaScript在网页中实现一个计算当年还剩多少时间的倒数计时程序,网页上能够实时动态显示“XX年还剩XX天XX时XX分XX秒”: 程序代码如下: <meta charset=" ...

  5. 1.Nexus安装与配置

    1.Nexus下载下载地址:http://www.sonatype.org/nexus/go/下载后的文件:nexus-2.11.4-01-bundle.zip安装:直接解压到某个目录即可解压后,会有 ...

  6. linux服务之ntp与chrony

    centos7.2变成了chrony RHEL从7.0开始改用chrony同步时间,原ntp同步方式也可以使用,但要安装ntp服务. [root@1st-kvm plymouth]# rpm -qa| ...

  7. web前端面试2

    百度另外一部门面试 1.前端html5新特性 2.数组常用函数 3.前后台json树形结构遍历,对算法的了解 4.css3背景属性设置为适合匹配模块的属性是什么 5.jquery插件的写法 6.研究过 ...

  8. Spring和SpringMVC的区别

    spring 是是一个开源框架,是为了解决企业应用程序开发,功能如下◆目的:解决企业应用开发的复杂性◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能◆范围:任何Java应用简单 ...

  9. mysql 10进制与35进制之间的转换 注意Power处理bigint的问题

    35进制的目的是防止0和O造成的视觉误差 BEGIN    DECLARE m_StrHex35 VARCHAR(100); -- 返回35进制表示的结果  DECLARE m_Remainder B ...

  10. Android 抽屉类SlidingDrawer的使用

     比较简单,设置好SlidingDrawer控件的handle和content属性就可以了.  android:content="@+id/content"  android:ha ...