java链式编程_Java链式编程学习

Java链式编程

在使用jquery时肯定对它的链式编程惊艳到,慢慢的其它语言这种编程模式也逐渐增多。其本身并不复杂,在调用方法时,方法最后返回对象本身,以达到链式编程的效果。

链式编程比较简单,只要return this即可具有相应的编程模式,但是需要根据业务需求使用不同的方法方式进行实现。

简单的链式编程

既然使用return this可以实现链式模式,那就依次为方案,实现一个简单的例子。

public class Book {

private String bookId;

private String title;

private String cover;

public String getBookId() {

return bookId;

}

public Book setBookId(String bookId) {

this.bookId = bookId;

// 返回当前对象

return this;

}

public String getTitle() {

return title;

}

public Book setTitle(String title) {

this.title = title;

// 返回当前对象

return this;

}

public String getCover() {

return cover;

}

public Book setCover(String cover) {

this.cover = cover;

// 返回当前对象

return this;

}

@Override

public String toString() {

return "Book{" +

"bookId='" + bookId + '\'' +

", title='" + title + '\'' +

", cover='" + cover + '\'' +

'}';

}

}

代码比较简单,就是一个图书的模型,将三个字段的Set方法都返回了对象本身。看一下调用

public static void main(String[] args) {

Book book = new Book().setBookId("b.001").setTitle("庆余年").setCover("http://localhost/qyn.jpg");

System.out.println(book);

}

// Book{bookId='b.001', title='庆余年', cover='http://localhost/qyn.jpg'}

编码过程中,完成一个Set方法后按下.就会继续提醒其他方法,实现了链式编程的效果。并且最终结果也符合预期。

静态初始化方法of

目前Spring中有很多方法提供了静态of方法,可以更方便的创建对象,结合return this将更为实用的实现链式编程,算是一种比较不错得扩展措施。在这种模式中,大量的使用了of替代了构造函数。

public class Pageable {

// 页码,从1开始

private long page;

// 页大小

private int size;

// 结果命中数量

private long count;

private Pageable(long page, int size) {

this.page = page;

this.size = size;

}

private Pageable(long page, int size, long count) {

this(page, size);

this.count = count;

}

// PageRequest时使用

public static Pageable of(long page, int size) {

return of(page, size, 0);

}

// 返回结果时,具有命中数量及返回总页码计算使用

public static Pageable of(long page, int size, long count) {

return new Pageable(page, size, count);

}

// 分页时,获取偏移量

public long getOffset() {

return (page - 1) * size;

}

// 返回总页码

public long getPageCount() {

return (long) Math.ceil((double) count / size);

}

public long getPage() {

return this.page;

}

public int getSize() {

return this.size;

}

public long getCount() {

return this.count;

}

}

上面示例中的分页工具类,只实现了三个成员变量页码、页大小、条目数,并且未实现成员变量的Set方法;构造方法全部为私有,实现了静态的of方法来创建分页对象。在该对象中同时提供了获取分页偏移量的getOffset方法,以及计算出总页码的getPageCount方法。

该工具一般有两种使用场景:

数据库查询后,返回数据列表以及分页信息,此时需要页码、页大小、条目数三个信息,使用及实现都比较方便

内存分页时,可以提供一个分页偏移量的计算方法

public static void main(String[] args) {

Pageable pageable = Pageable.of(10, 10, 123);

System.out.println(pageable.getOffset());

System.out.println(pageable.getPageCount());

}

// 90

// 13

如果采用FastJson进行序列化,上述设计方式也能够满足返回JSON的需求,FastJson按照Get方法进行生成属性列表。

public static void main(String[] args) {

System.out.println(JSON.toJSONString(Pageable.of(10, 10, 123)));

}

// {"count":123,"offset":90,"page":10,"pageCount":13,"size":10}

Builder模式链式编程

Builder模式也是目前较为常用的一种链式编程方法,目前Spring中有大量的依据此模式进行的编码。以最为常见的ResponseEntity(或者Swagger模块也大量采用了此类方法)类来看,其内部定义了Builder接口,并默认实现了一个DefaultBuild内部类,内部方法采用return this实现链式模式,同时在ResponseEntity中提供了类似的Builder方法,如ok、status等静态方法。

从这些类的实现原理看,实现Builder模式也比较简单,一方面创建一个内部Builder类,实现相应信息的创建;同时在目标类中,实现一个静态的builder方法,用于创建Builder对象,并启动链式模式;最后再由内部类提供一个终止方法,该终止方法将完成目标类的创建。

public class ApiInfo {

private String name;

private String description;

private String url;

private Map params;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getDescription() {

return description;

}

public void setDescription(String description) {

this.description = description;

}

public String getUrl() {

return url;

}

public void setUrl(String url) {

this.url = url;

}

public Map getParams() {

return params;

}

public void setParams(Map params) {

this.params = params;

}

@Override

public String toString() {

return "ApiInfo{" +

"name='" + name + '\'' +

", description='" + description + '\'' +

", url='" + url + '\'' +

", params=" + params +

'}';

}

public static ApiBuilder builder() {

return new ApiBuilder();

}

// 内部Builder类

public static class ApiBuilder {

private String name;

private String description;

private String url;

private Map params;

// name信息设置,链式

public ApiBuilder name(String name) {

this.name = name;

return this;

}

// 注释信息设置

public ApiBuilder description(String description) {

this.description = description;

return this;

}

public ApiBuilder url(String url) {

this.url = url;

return this;

}

// 参数信息设置

public ApiBuilder params(String name, String description) {

this.params = Optional.ofNullable(params).orElseGet(() -> Maps.newHashMap());

this.params.put(name, description);

return this;

}

// 创建ApiInfo对象

public ApiInfo build() {

ApiInfo apiInfo = new ApiInfo();

apiInfo.setName(this.name);

apiInfo.setDescription(this.description);

apiInfo.setUrl(this.url);

apiInfo.setParams(this.params);

return apiInfo;

}

}

}

上述示例采用Builder模式实现了一个Api接口信息的对象设计,主要是能够设置接口名、地址以及相应的参数。内部设计了一个ApiBuilder,可以实现链式属性设置,并最终提供一个build方法用于终止时创建目标实例。

public static void main(String[] args) {

ApiInfo apiInfo = ApiInfo.builder().name("获取资源信息")

.description("根据资源ID获取资源信息")

.url("/resource/:id")

.params("id", "资源唯一ID")

.params("token", "令牌")

.build();

System.out.println(apiInfo);

}

// ApiInfo{name='获取资源信息', description='根据资源ID获取资源信息', url='/resource/:id', params={id=资源唯一ID, token=令牌}}

lombok链式编程

链式编程比较简单,一般也就是return、静态of、Builder几种模式,可以直接编码实现,Spring以及一些开源项目Swagger等等都是这么做的。如果我们不是为了做一个通用的开源产品,只是业务性的编码,此时不需要通过大量的编码去实现链式编程,可以采用lombok进行实现,使用也比较简单。

使用lombok时,可以通过maven引入,也可以通过idea安装插件的方式引入。

return链式

仍然使用此前的例子Book类,进行改造,采用lombok注解进行编码。

lombok实现return this链式,只需要在类添加注释@Accessors(chain = true)即可实现

@Getter

@Setter

@ToString

@Accessors(chain = true)

public class Book {

private String bookId;

private String title;

private String cover;

public static void main(String[] args) {

Book book = new Book().setBookId("b.001").setTitle("庆余年").setCover("http://localhost/qyn.jpg");

System.out.println(book);

}

}

如果在IDE中,查看类接口(ctrl+o),可以发现属性的Set方法,返回类型为Book,和自己编码的方案一致。

public static void main(String[] args) {

Book book = new Book().setBookId("b.001").setTitle("庆余年").setCover("http://localhost/qyn.jpg");

System.out.println(book);

}

// Book{bookId='b.001', title='庆余年', cover='http://localhost/qyn.jpg'}

静态初始化方法

对Pageable类进行改造,使用lombok实现of方法。

静态of方法的添加,需要通过lombok的构造函数注解进行添加,RequiredArgsConstructor可以实现必备参数列表的构造,并通过staticname指定静态方法为of;针对上例中的Pageable对象提供了两种静态构造方法,一种是只需要指定页码和页大小即可,还有一种是全部参数的构造函数,可以计算总页码;RequiredArgsConstructor可以实现必备参数的构造;AllArgsConstructor实现全部参数的构造函数,并指定staticName为of,通过lombok的注解组合,实现Pageable与上例自己编码同等效果。

@Getter

@ToString

@Accessors(chain = true)

@RequiredArgsConstructor(staticName = "of")

@AllArgsConstructor(staticName = "of")

public class Pageable {

/**

* 页码,从1开始

*/

@NonNull

private long page;

/**

* 页大小

*/

@NonNull

private int size;

/**

* 结果命中数量

*/

private long count;

/**

* 分页时,获取偏移量

*

* @return

*/

public long getOffset() {

return (page - 1) * size;

}

/**

* 返回总页码

*

* @return

*/

public long getPageCount() {

return (long) Math.ceil((double) count / size);

}

}

通过组合注释实现了同样的效果,使用也和原有编码效果等同。

public static void main(String[] args) {

Pageable pageable = Pageable.of(10, 10);

System.out.println(pageable.getOffset());

// 全部构造

System.out.println(JSON.toJSONString(Pageable.of(10, 10, 123)));

}

// 90

// {"count":123,"offset":90,"page":10,"pageCount":13,"size":10}

Builder模式

对ApiInfo进行改造,使用lombok实现builder模式。

lombok实现Builder模式,只要添加@Builder注解即可

@Getter

@Setter

@Builder

@ToString

public class ApiInfo {

private String name;

private String description;

private String url;

private Map params;

}

使用上和之前的例子差不多,不过对于params默认只能是Set的形式。

public static void main(String[] args) {

ApiInfo apiInfo = ApiInfo.builder().name("获取资源信息")

.description("根据资源ID获取资源信息")

.url("/resource/:id")

.params(new HashMap() {

{

put("id", "资源唯一ID");

put("token", "令牌");

}

})

.build();

System.out.println(apiInfo);

}

// ApiInfo(name=获取资源信息, description=根据资源ID获取资源信息, url=/resource/:id, params={id=资源唯一ID, token=令牌})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值