在构建大对象时,对象的属性比较多,我们可以采用一个构造器或者使用空的构造器构造,然后使用setter方法去设置。在使用者使用这些方法时,会很多冗长的构造器参数列表或者setter方法。我们可以使用Builder模式来简化大对象的构造,提高代码的简洁性,同时提高使用者的编码体验。

下面我们将介绍在Java8之前、使用极简代码利器Lombok、Java8之后的Builder模式。

Pre Java8

我们先来看下在Java8之前的Builder模式

public class Order {private String code;private List<String> offers;private Map<String, Object> features;public static Order.Builder builder(){return new Builder();}//省略getter setterpublic static class Builder {private OrderState orderState = new OrderState();private static final BeanCopier orderCopier = BeanCopier.create(OrderState.class, Order1.class, false);private class OrderState {private String code;private Map<String, Object> features;private List<String> offers;//省略getter setter}public Builder code(String code) {orderState.code = code;return this;}public Builder features(Map<String, Object> features) {orderState.features = features;return this;}public <T> Builder feature(String key, T obj) {if (orderState.features == null) {orderState.features = new HashMap<>();}orderState.features.put(key, obj);return this;}public Builder offers(List<String> offers) {orderState.offers = offers;return this;}public Builder offer(String offer) {if (orderState.offers == null) {orderState.offers = new ArrayList<>();}orderState.offers.add(offer);return this;}public Order build() {Order order = new Order();orderCopier.copy(orderState, order1, null);orderState = null;return order;}}
}

以上代码看上去很冗长,而且IDE没有提供自动的生成工具,这也是我们目前在工程代码里看到这种模式的比较少的原因之一。但是对于这个类的使用者来说,提高了很高的代码体验。在使用者,使用这个类时如下:

Order order = Order.builder().code("1235").offer("满100减5").feature("category", "shoe").build();

一个类的定义通常只会有一个地方,而使用这个类的地方会有很多,在定义类时为使用者多考虑一些,就能为使用这个类的开发者提高很多效率,同时让整个团队的代码变的更加简洁。

我一直认为一个类的设计和一个产品的设计者理念相同,产品经理设计一个功能首先能解决用户的痛点,同时还要提高用户体验,让用户用着爽。同样设计一个基础类,需要解决一个业务问题,同时需要从使用者的角度考虑,让使用者用着爽。一个优秀的基础类的设计者需要一点产品思维,代码就是你的产品。

Lombok

以上代码对于类的使用者来说,用着很爽,但是对于类的开发者来说,不够友好,而且会有很多看似重复的代码。对于类的开发者来说,这个类难以维护。对于开发者来说,永远不要去做重复的事情,既然这件事情是有规律的、重复的。对于这样的事情,程序更加擅长。

Lombok是一个可以让Java代码变的更加简洁、让你的开发更加高效的利器。使用了Lombok之后,我们不需要写Getter&Setter、ToString等方法,这些都可以通过注解来代替,在编译期间,Lombok会帮助你生成相应的字节码。所以也不用担心性能损失。Lombok也支持了Builder模式,你可以用几个注解来代替以上冗余的代码。

@Builder
public class Order {private String code;@Singularprivate List<String> offers;@Singularprivate Map<String, Object> features;
}

我们使用时

Order order = Order.builder().code("1234").offer("满100减5").feature("category", "category").build();

以上我们就是用了@Builder、@Singular实现了以上冗长的代码。是不是很简洁?在编译阶段,会帮助我们生成类似上面冗长代码相同的字节码。

在开发时,Lombok需要IDE插件的支持,所以你如果在工程代码中使用,需要团队达成共识,并安装插件。

Java8

使用Java8之后,对于Builder模式我们有了新的方法,我们可以利用Supplier、Consumer来构造一个通用的Builder模式,具体代码如下:

public class GenericBuilder<T> {private final Supplier<T> instantiator;private List<Consumer<T>> instantiatorModifiers = new ArrayList<>();private List<Consumer<T>> keyValueModifiers = new ArrayList<>();public GenericBuilder(Supplier<T> instantiator) {this.instantiator = instantiator;}public static <T> GenericBuilder<T> of(Supplier<T> instantiator) {return new GenericBuilder<T>(instantiator);}public <U> GenericBuilder<T> with(BiConsumer<T, U> consumer, U value) {Consumer<T> c = instance -> consumer.accept(instance, value);instantiatorModifiers.add(c);return this;}public <K, V> GenericBuilder<T> with(KeyValueConsumer<T, K, V> consumer, K key, V value) {Consumer<T> c = instance -> consumer.accept(instance, key, value);keyValueModifiers.add(c);return this;}public T build() {T value = instantiator.get();instantiatorModifiers.forEach(modifier -> modifier.accept(value));keyValueModifiers.forEach(keyValueModifier -> keyValueModifier.accept(value));instantiatorModifiers.clear();keyValueModifiers.clear();return value;}
}

Order类定义

 public class Order {private String code;private List<String> offers;private Map<String, Object> features;public void addOffer(String offer) {offers = Optional.ofNullable(offers).orElseGet(ArrayList::new);offers.add(offer);}public <T> void addFeature(String key, T value) {features = Optional.ofNullable(features).orElseGet(HashMap::new);features.put(key, value);}//省略getter setter
}

在使用时如下:

Order order = GenericBuilder.of(Order::new).with(Order::setCode, "123232").with(Order::addOffer, "满100减5").with(Order::addFeature, "category", "shoe").build();

在Java8中,使用通用Builder的方法,简化了代码开发,和Pre Java8相比要简洁很多。相对于Lombok来说,由于仍然要生成getter&setter方法,还是没有使用Lombok简洁。但是它利用Java8的特性,不需要提供额外第三包的支持。

欢迎关注我的公众号MyArtNote

如何实现Builder模式相关推荐

  1. Java 常用设计模式 -- Builder模式

    Builder模式是在Java中最流行的模式之一.它很简单,有助于保持对象不可变,并且可以使用Project Lombok的@Builder或Immutables等工具生成,仅举几例. 模式的流畅变体 ...

  2. Creational模式之Builder模式

    1.意图 将一个复杂对象的构建与它表示分离,使得相同的构建过程能够创建不同的表示. 查看很多其它请点击 2.别名 无 3.动机 一个RTF(Rich Text Format)文档交换格式的阅读器应能将 ...

  3. 可扩展性的builder模式的构建方法

    http://www.cnblogs.com/happyhippy/archive/2010/09/01/1814287.html 使用builder模式的时候: 本篇文章的原因:builder模式接 ...

  4. GOF对Builder模式的定义(转载)

    (1)意图 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. (2)适用性 1. 当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式: 2. 当构造过程必须允许 ...

  5. 创建型模式之Builder模式

    1.意图 将一个复杂对象的创建与它的表示分享,使得同样的构建过程可以创建不同的表示. 2.适用性 (1)当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时 (2)当构造过程必须允许被构 ...

  6. java设计模式:Builder模式

    Builder模式关键是在建立对象是一步一步处理 package customer;class Starbucks {private String size;private String drink; ...

  7. JAVA Builder模式构建MAP/LIST的示例

    我们在构建一个MAP时,要不停的调用put,有时候看着觉得很麻烦,刚好,看了下builder模式,觉得这思路不错,于是乎,照着用builder模式写了一个构建MAP的示例,代码如下: import j ...

  8. 设计模式-Builder模式

    目录 一个例子(做汤) 人工做汤 机器做汤(使用Builder模式) 优缺点 优点 缺点 Builder模式属于创建型模式. 它是将一个复杂对象的构建过程隐藏起来,让使用者只关系自己要生成什么样的对象 ...

  9. Intellij idea generate builder 插件-用于自动生成builder模式代码

    2019独角兽企业重金招聘Python工程师标准>>> 目的:开发中喜欢builder模式去构造一个实例,而当一个对象的属性过多的时候,手动的去完成一个类的builder是很繁琐的: ...

  10. java的设计模式 - Builder模式

    Builder 模式的目的? 构造对象的方式过于复杂,不如将之抽离出来.比如,构造器参数过多 这样说也有点抽象,举个例子吧. 举个例子 比如 非常热门的消息队列RabbitMQ 的 AMQP.Basi ...

最新文章

  1. Apache的服务端包含--SSI
  2. 挑灯熬夜看《Build 2015 Keynote》图文笔记
  3. 有关于Java Map,应该掌握的8个问题
  4. 【学习笔记11】动态方法调用和使用通配符定义action
  5. PHPExcel+phalcon+yii批量导入
  6. c语言标准差怎么计算,一个关于文段统计的问题,怎么在运行过程中计算标准差?...
  7. 混合云备份服务 > 产品简介 > 什么是混合云备份
  8. js parsefloat 精度_javascript中的float运算精度
  9. python语法简图
  10. AgileEAS.NET平台开发实例-药店系统-视频教程系列-索引
  11. matlab模板图像匹配,基于Matlab 图像匹配――模板匹配
  12. 为什么程序员做外包会被瞧不起?
  13. 邮箱正则不能超过50位_投资超50亿元的安吉景区,在悬崖顶荡秋千,超过160斤不能玩...
  14. __I、 __O 、__IO是什么意思?怎么用?
  15. 信用证的好处!只要有信用证,没有不符点,就能收到钱!
  16. 苹果输入法怎么换行_现在还有没有必要学习五笔输入法呢
  17. 上线两个月,微信小程序给那些用身体支持它的人带来了什么?
  18. CTF.show:新春红包题wp
  19. 690. Employee Importance
  20. 语法基础——PHP语法基础

热门文章

  1. lsof Linux
  2. python基础知识下载_python基础知识(实用)
  3. TK 设置tkinter窗口的置顶属性,保持最上层
  4. SQUID工作原理是什么
  5. 《流浪地球》登顶IMAX国产片历史最高票房
  6. GPIO 配置之ODR, BSRR, BRR 详解
  7. vue 点击遮罩层功能区以外的地方关闭遮罩层
  8. 贵有恒,若事事勤思善问,何患不一日千里?--惭愧
  9. 如何将png图片转为heif格式
  10. GitHub中Organization的Member邀请和clone代码库