美文网首页Java开发
Java链式编程学习

Java链式编程学习

作者: 李小磊_0867 | 来源:发表于2020-01-30 18:42 被阅读0次

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<String, String> 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<String, String> getParams() {
        return params;
    }

    public void setParams(Map<String, String> 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<String, String> 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实现全部参数的构造函数,并指定staticNameof,通过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<String, String> params;
}

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

public static void main(String[] args) {
    ApiInfo apiInfo = ApiInfo.builder().name("获取资源信息")
            .description("根据资源ID获取资源信息")
            .url("/resource/:id")
            .params(new HashMap<String, String>() {
                {
                    put("id", "资源唯一ID");
                    put("token", "令牌");
                }
            })
            .build();
    System.out.println(apiInfo);
}
// ApiInfo(name=获取资源信息, description=根据资源ID获取资源信息, url=/resource/:id, params={id=资源唯一ID, token=令牌})

相关文章

  • Java链式编程学习

    Java链式编程 在使用jquery时肯定对它的链式编程惊艳到,慢慢的其它语言这种编程模式也逐渐增多。其本身并不复...

  • Java链式编程

    概念 所谓链式,也就是每次调用对象方法后返回的都是该对象本身,而该对象又可以继续调用方法。 例子

  • jQuery 链式编程

    jQuery 链式编程 链式编程原理 链式编程代码示例 隐式迭代

  • 链式编程思想

    链式编程思想 链式编程思想

  • iOS 链式编程

    链式编程 主要介绍链式编程原理,以及如何创建链式编程 编程范式 在介绍链式编程之前,首先来了解下什么是编程范式。 ...

  • 链式编程(Java写法)

    在我们编写代码过程中听到过很多说法如:面向切面编程,函数式编程,面向对象编程,泛式编程等等接着我来说下链式编程普通...

  • iOS链式编程

    前言 通过对Masonry的学习,我们了解了链式编程的思想。此片文章是使用链式编程的思想做一个计算机,练习一下链式...

  • ReactiveObjC入门

    ReactiveObjC基础用法 iOS开发三种编程方式(响应式编程、函数编程、链式编程),函数编程最常用,链式编...

  • 工作iOS技术总结

    链式编程、函数式、面向接口编程思想 iOS 之ReactiveCocoa 链式编程2 WKWebView的缓存处理...

  • 一、链式编程思想、响应式编程思想和函数式编程

    1. 链式编程思想 链式编程思想的核心就是方法的返回值必须是Block,Masonry是链式编程思想应用的代表。 ...

网友评论

    本文标题:Java链式编程学习

    本文链接:https://www.haomeiwen.com/subject/wbxwthtx.html