Java8 Builder

new创建对象的写法

定义类GirlFirend

  1. public class GirlFriend {
  2. private String name;
  3. private int age;
  4. // 省略 getter & setter ...
  5. public static void main(String[] args) {
  6. GirlFriend myGirlFriend = new GirlFriend();
  7. myGirlFriend.setName("小美");
  8. myGirlFriend.setAge(18);
  9. }
  10. }

类属性多的情况

  1. public class GirlFriend {
  2. private String name;
  3. private int age;
  4. private int bust;
  5. private int waist;
  6. private int hips;
  7. private List<String> hobby;
  8. private String birthday;
  9. private String address;
  10. private String mobile;
  11. private String email;
  12. private String hairColor;
  13. private Map<String, String> gift;
  14. // 等等等等 ...
  15. // 省略 getter & setter ...
  16. public static void main(String[] args) {
  17. GirlFriend myGirlFriend = new GirlFriend();
  18. myGirlFriend.setName("小美");
  19. myGirlFriend.setAge(18);
  20. myGirlFriend.setBust(33);
  21. myGirlFriend.setWaist(23);
  22. myGirlFriend.setHips(33);
  23. myGirlFriend.setBirthday("2001-10-26");
  24. myGirlFriend.setAddress("上海浦东");
  25. myGirlFriend.setMobile("18688888888");
  26. myGirlFriend.setEmail("pretty-xiaomei@qq.com");
  27. myGirlFriend.setHairColor("浅棕色带点微卷");
  28. List<String> hobby = new ArrayList<>();
  29. hobby.add("逛街");
  30. hobby.add("购物");
  31. hobby.add("买东西");
  32. myGirlFriend.setHobby(hobby);
  33. Map<String, String> gift = new HashMap<>();
  34. gift.put("情人节礼物", "LBR 1912女王时代");
  35. gift.put("生日礼物", "迪奥烈焰蓝金");
  36. gift.put("纪念日礼物", "阿玛尼红管唇釉");
  37. myGirlFriend.setGift(gift);
  38. // 等等等等 ...
  39. }
  40. }

使用 new 关键字实例化类GirlFriend

  1. GirlFriend girlFriend = new GirlFriend{name='小美'
  2. , age=18
  3. , bust=33
  4. , waist=23
  5. , hips=33
  6. , hobby=[逛街, 购物, 买东西]
  7. , birthday='2001-10-26'
  8. , address='上海浦东'
  9. , mobile='18688888888'
  10. , email='pretty-xiaomei@qq.com'
  11. , hairColor='浅棕色带点微卷'
  12. , gift={情人节礼物=LBR 1912女王时代, 生日礼物=迪奥烈焰蓝金, 纪念日礼物=阿玛尼红管唇釉}
  13. }

缺点:使用new 方式创建对象时,需要根据构造器指定的参数才能正确创建对象,而且在不同场景下需要创建不同的构造器方法才能应对不同情况的实例化。可以看出其中的麻烦程度。

通过通用Builder来创建对象

通用Builder方式创建对象:适用于所有类,不需要改造原来类,不需要 lombok 插件支持。

示例代码

  1. public class GirlFriend {
  2. // 省略属性 ...
  3. // 省略 getter & setter ...
  4. // 为了演示方便,加几个聚合方法
  5. public void addHobby(String hobby) {
  6. this.hobby = Optional.ofNullable(this.hobby).orElse(new ArrayList<>());
  7. this.hobby.add(hobby);
  8. }
  9. public void addGift(String day, String gift) {
  10. this.gift = Optional.ofNullable(this.gift).orElse(new HashMap<>());
  11. this.gift.put(day, gift);
  12. }
  13. public void setVitalStatistics(int bust, int waist, int hips) {
  14. this.bust = bust;
  15. this.waist = waist;
  16. this.hips = hips;
  17. }
  18. public static void main(String[] args) {
  19. GirlFriend myGirlFriend = Builder.of(GirlFriend::new)
  20. .with(GirlFriend::setName, "小美")
  21. .with(GirlFriend::setAge, 18)
  22. .with(GirlFriend::setVitalStatistics, 33, 23, 33)
  23. .with(GirlFriend::setBirthday, "2001-10-26")
  24. .with(GirlFriend::setAddress, "上海浦东")
  25. .with(GirlFriend::setMobile, "18688888888")
  26. .with(GirlFriend::setEmail, "pretty-xiaomei@qq.com")
  27. .with(GirlFriend::setHairColor, "浅棕色带点微卷")
  28. .with(GirlFriend::addHobby, "逛街")
  29. .with(GirlFriend::addHobby, "购物")
  30. .with(GirlFriend::addHobby, "买东西")
  31. .with(GirlFriend::addGift, "情人节礼物", "LBR 1912女王时代")
  32. .with(GirlFriend::addGift, "生日礼物", "迪奥烈焰蓝金")
  33. .with(GirlFriend::addGift, "纪念日礼物", "阿玛尼红管唇釉")
  34. // 等等等等 ...
  35. .build();
  36. }
  37. }

实例化和属性设置在同一条语句执行,链式操作,非常简洁!

通用Builder的定义

  1. /**
  2. * 通用的 Builder 模式构建器
  3. *
  4. * @author: Fcant
  5. * @since 2019/8/29
  6. */
  7. public class Builder<T> {
  8. private final Supplier<T> instantiator;
  9. private List<Consumer<T>> modifiers = new ArrayList<>();
  10. public Builder(Supplier<T> instantiator) {
  11. this.instantiator = instantiator;
  12. }
  13. public static <T> Builder<T> of(Supplier<T> instantiator) {
  14. return new Builder<>(instantiator);
  15. }
  16. public <P1> Builder<T> with(Consumer1<T, P1> consumer, P1 p1) {
  17. Consumer<T> c = instance -> consumer.accept(instance, p1);
  18. modifiers.add(c);
  19. return this;
  20. }
  21. public <P1, P2> Builder<T> with(Consumer2<T, P1, P2> consumer, P1 p1, P2 p2) {
  22. Consumer<T> c = instance -> consumer.accept(instance, p1, p2);
  23. modifiers.add(c);
  24. return this;
  25. }
  26. public <P1, P2, P3> Builder<T> with(Consumer3<T, P1, P2, P3> consumer, P1 p1, P2 p2, P3 p3) {
  27. Consumer<T> c = instance -> consumer.accept(instance, p1, p2, p3);
  28. modifiers.add(c);
  29. return this;
  30. }
  31. public T build() {
  32. T value = instantiator.get();
  33. modifiers.forEach(modifier -> modifier.accept(value));
  34. modifiers.clear();
  35. return value;
  36. }
  37. /**
  38. * 1 参数 Consumer
  39. */
  40. @FunctionalInterface
  41. public interface Consumer1<T, P1> {
  42. void accept(T t, P1 p1);
  43. }
  44. /**
  45. * 2 参数 Consumer
  46. */
  47. @FunctionalInterface
  48. public interface Consumer2<T, P1, P2> {
  49. void accept(T t, P1 p1, P2 p2);
  50. }
  51. /**
  52. * 3 参数 Consumer
  53. */
  54. @FunctionalInterface
  55. public interface Consumer3<T, P1, P2, P3> {
  56. void accept(T t, P1 p1, P2 p2, P3 p3);
  57. }
  58. }

这个示例最多支持三个参数的设置属性方法,应对普通场景完全够用。如果要扩展也很容易,添加多个参数的Consumer即可。