[设计模式/Java] 设计模式之建造者模式【10】
1 概述:建造者模式
模式定义
- 
建造者模式是一种创建型设计模式,它允许你创建复杂对象的【步骤】与【表示方式】相分离。 
- 
主要目的: 将一个复杂对象的【构建过程】与其【表示】相分离,从而可以创建具有不同表示形式的对象。 
模式的组成
建造者模式包含以下几个主要角色:
- 产品(Product):要构建的复杂对象。产品类通常包含多个部分或属性。
- 抽象建造者(Builder):定义了构建产品的抽象接口,包括构建产品的各个部分的方法。
- 具体建造者(Concrete Builder):实现抽象建造者接口,具体确定如何构建产品的各个部分,并负责返回最终构建的产品。
- 指导者(Director):负责调用建造者的方法来构建产品,指导者并不需要了解具体的构建过程,只需关心产品的构建顺序和方式。
模式特点
优点
- 分离构建过程和表示,使得构建过程更加灵活,可以构建不同的表示。
- 可以更好地控制构建过程,隐藏具体构建细节。
- 如:构建过程中,校验部分字段的值内容
- 
代码复用性高,可以在不同的构建过程中重复使用相同的建造者。 
- 
减少客户端创建复杂对象的代码量 
缺点
- 如果产品的属性较少,建造者模式可能会导致代码冗余。
- 增加了系统的类和对象数量。
适用场景
- 
主要解决:在软件系统中,一个复杂对象的创建通常由多个部分组成,这些部分的组合经常变化,但组合的算法相对稳定。 
- 
何时使用: 
- 当一些基本部件不变,而其组合经常变化时。
- 需要生成的对象具有复杂的内部结构。
- 需要生成的对象内部属性相互依赖。
- 如何解决?
- 将变与不变的部分分离开。
案例实践
案例:快餐厅的套餐
案例描述
- 
去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出不同的"套餐"。 
- 
我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。 
- 汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。
- 冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。
- 
我们将创建一个表示食物条目(比如汉堡和冷饮)的 Item接口和实现Item接口的实体类;
 以及一个表示食物包装的Packing接口和实现Packing接口的实体类,汉堡是包在纸盒中,冷饮是装在瓶子中。
- 
然后,我们创建一个 Meal类,带有Item的ArrayList和一个通过结合Item来创建不同类型的Meal对象的MealBuilder。BuilderPatternDemo类使用MealBuilder来创建一个Meal。

Iteam / Packing : 创建一个表示食物条目和食物包装的接口
- Item
public interface Item {
   public String name();
   public Packing packing();
   public float price();    
}
- Packing
public interface Packing {
   public String pack();
}
Wrapper : 创建实现 Packing 接口的实体类
- Wrapper
public class Wrapper implements Packing {
   @Override
   public String pack() {
      return "Wrapper";
   }
}
- Bottle
public class Bottle implements Packing {
   @Override
   public String pack() {
      return "Bottle";
   }
}
Burger / ColdDrink : 创建实现 Item 接口的抽象类,该类提供了默认的功能
- Burger
public abstract class Burger implements Item {
 
   @Override
   public Packing packing() {
      return new Wrapper();
   }
 
   @Override
   public abstract float price();
}
- ColdDrink
public abstract class ColdDrink implements Item {
 
    @Override
    public Packing packing() {
       return new Bottle();
    }
 
    @Override
    public abstract float price();
}
VegBurger / ChickenBurger / Coke / Pepsi : 创建扩展了 Burger 和 ColdDrink 的实体类
- VegBurger
public class VegBurger extends Burger {
   @Override
   public float price() {
      return 25.0f;
   }
 
   @Override
   public String name() {
      return "Veg Burger";
   }
}
- ChickenBurger
public class ChickenBurger extends Burger {
 
   @Override
   public float price() {
      return 50.5f;
   }
 
   @Override
   public String name() {
      return "Chicken Burger";
   }
}
- Coke
public class Coke extends ColdDrink {
 
   @Override
   public float price() {
      return 30.0f;
   }
 
   @Override
   public String name() {
      return "Coke";
   }
}
- Pepsi
public class Pepsi extends ColdDrink {
 
   @Override
   public float price() {
      return 35.0f;
   }
 
   @Override
   public String name() {
      return "Pepsi";
   }
}
Meal : 创建一个 Meal 类,带有上面定义的 Item 对象
- Meal : 英译
- n. 一餐;早(或午、晚)餐;一餐所吃的食物;谷物粗粉(用作饲料或加工面粉)
- v. 吃饭;碾碎
import java.util.ArrayList;
import java.util.List;
 
public class Meal {
   private List<Item> items = new ArrayList<Item>();    
 
   public void addItem(Item item){
      items.add(item);
   }
 
   public float getCost(){
      float cost = 0.0f;
      for (Item item : items) {
         cost += item.price();
      }        
      return cost;
   }
 
   public void showItems(){
      for (Item item : items) {
         System.out.print("Item : "+item.name());
         System.out.print(", Packing : "+item.packing().pack());
         System.out.println(", Price : "+item.price());
      }        
   }    
}
MealBuilder : 创建一个 MealBuilder 类,实际的 builder 类负责创建 Meal 对象
public class MealBuilder {
 
   public Meal prepareVegMeal (){
      Meal meal = new Meal();
      meal.addItem(new VegBurger());
      meal.addItem(new Coke());
      return meal;
   }   
 
   public Meal prepareNonVegMeal (){
      Meal meal = new Meal();
      meal.addItem(new ChickenBurger());
      meal.addItem(new Pepsi());
      return meal;
   }
}
BuilderPatternDemo : BuiderPatternDemo 使用 MealBuilder 来演示建造者模式
public class BuilderPatternDemo {
   public static void main(String[] args) {
      MealBuilder mealBuilder = new MealBuilder();
 
      Meal vegMeal = mealBuilder.prepareVegMeal();
      System.out.println("Veg Meal");
      vegMeal.showItems();
      System.out.println("Total Cost: " +vegMeal.getCost());
 
      Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
      System.out.println("\n\nNon-Veg Meal");
      nonVegMeal.showItems();
      System.out.println("Total Cost: " +nonVegMeal.getCost());
   }
}
out
Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0
Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5
案例:Java StringBuilder
- Java中的- StringBuilder。
案例:Lombok 对 Java 实体Bean 的@Builder注解
基本使用
@Builder注释为你的类生成相对略微复杂的构建器API。@Builder可以让你以下面显示的那样调用你的代码,来初始化你的实例对象:
Student.builder()
  .no( "001" )
  .name( "admin" )
  .birthday( 18 )
  .phone( "110" )
  .build();
- @Builder可以放在类、构造函数或方法上。
虽然放在类上和放在构造函数上这两种模式是最常见的用例,但
@Builder最容易用放在方法的用例来解释。
原理
- 那么@Builder内部帮我们做了什么?
- 创建一个名为
ThisClassBuilder的内部静态类,并具有和实体类形同的属性(称为构建器)。- 在构建器中:对于目标类中的所有的属性和未初始化的
final字段,都会在构建器中创建对应属性。- 在构建器中:创建一个无参的
default构造函数。- 在构建器中:对于实体类中的每个参数,都会对应创建类似于setter的方法,只不过方法名与该属性名相同。 且返回值是构建器本身(便于链式调用),如上例所示。
- 在构建器中:一个
build()方法,调用此方法,就会根据设置的值进行创建实体对象。- 在构建器中:同时也会生成一个
toString()方法。- 在实体类中:会创建一个
builder()方法,它的目的是用来创建构建器。
- 例如:
@Builder
public class User {
    private final Integer code = 200;
    private String username;
    private String password;
}
编译后:
// 编译后:
public class User {
    private String username;
    private String password;
    User(String username, String password) {
        this.username = username; this.password = password;
    }
    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }
    public static class UserBuilder {
        private String username;
        private String password;
        UserBuilder() {}
        public User.UserBuilder username(String username) {
            this.username = username;
            return this;
        }
        public User.UserBuilder password(String password) {
            this.password = password;
            return this;
        }
        public User build() {
            return new User(this.username, this.password);
        }
        public String toString() {
            return "User.UserBuilder(username=" + this.username + ", password=" + this.password + ")";
        }
    }
}
@Builder中配合使用 @Singular 注解,作用于【集合属性】
@Singular
- @Builder也可以为集合类型的参数或字段生成一种特殊的方法。
它采用修改列表中一个元素而不是整个列表的方式,可以是增加一个元素,也可以是删除一个元素。
Student.builder()
  .sno( "001" )
  .sname( "admin" )
  .sage( 18 )
  .sphone( "110" ).sphone( "112" )
  .build();
- 这样就可以轻松地将 List <String>字段中包含2个字符串。
但是想要这样来操作集合,你需要使用
@Singular来注释字段或参数。
- 在使用@Singular注释注释一个集合字段(使用@Builder注释类),lombok会将该构建器节点视为一个集合,并生成两个adder方法而不是setter方法。
- 一个向集合添加单个元素
- 一个将另一个集合的所有元素添加到集合中
- 将不生成仅设置集合(替换已添加的任何内容)的setter。 还生成了clear方法。
这些
singular构建器相对而言是有些复杂的,主要是来保证以下特性:
- 在调用
build()时,生成的集合将是不可变的。- 在调用
build()之后调用其中一个adder方法或clear方法不会修改任何已经生成的对象。如果对集合修改之后,再调用build(),则会创建一个基于上一个对象创建的对象实体。- 生成的集合将被压缩到最小的可行格式,同时保持高效。
- @Singular只能应用于- lombok已知的集合类型。目前,支持的类型有:
- java.util:
- Iterable, Collection, 和List (一般情况下,由压缩的不可修改的ArrayList支持).
- Set, SortedSet, and NavigableSet (一般情况下,生成可变大小不可修改的HashSet或者TreeSet).
- Map, SortedMap, and NavigableMap (一般情况下,生成可变大小不可修改的HashMap或者TreeMap).
- Guava’s com.google.common.collect:
- ImmutableCollection and ImmutableList
- ImmutableSet and ImmutableSortedSet
- ImmutableMap, ImmutableBiMap, and ImmutableSortedMap
- ImmutableTable
来看看使用了
@Singular注解之后的编译情况:
@Builder
public class User {
    private final Integer id;
    private final String zipCode = "123456";
    private String username;
    private String password;
    @Singular
    private List<String> hobbies;
}
编译后:
public class User {
    private final Integer id;
    private final String zipCode = "123456";
    private String username;
    private String password;
    private List<String> hobbies;
    User(Integer id, String username, String password, List<String> hobbies) {
        this.id = id; this.username = username;
        this.password = password; this.hobbies = hobbies;
    }
    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }
    public static class UserBuilder {
        private Integer id;
        private String username;
        private String password;
        private ArrayList<String> hobbies;
        UserBuilder() {
        }
        public User.UserBuilder id(Integer id) { this.id = id; return this; }
        public User.UserBuilder username(String username) { this.username = username; return this; }
        public User.UserBuilder password(String password) { this.password = password; return this; }
        public User.UserBuilder hobby(String hobby) {
            if (this.hobbies == null) {
                this.hobbies = new ArrayList();
            }
            this.hobbies.add(hobby);
            return this;
        }
        public User.UserBuilder hobbies(Collection<? extends String> hobbies) {
            if (this.hobbies == null) {
                this.hobbies = new ArrayList();
            }
            this.hobbies.addAll(hobbies);
            return this;
        }
        public User.UserBuilder clearHobbies() {
            if (this.hobbies != null) {
                this.hobbies.clear();
            }
            return this;
        }
        public User build() {
            List hobbies;
            switch(this.hobbies == null ? 0 : this.hobbies.size()) {
            case 0:
                hobbies = Collections.emptyList();
                break;
            case 1:
                hobbies = Collections.singletonList(this.hobbies.get(0));
                break;
            default:
                hobbies = Collections.unmodifiableList(new ArrayList(this.hobbies));
            }
            return new User(this.id, this.username, this.password, hobbies);
        }
        public String toString() {
            return "User.UserBuilder(id=" + this.id + ", username=" + this.username + ", password=" + this.password + ", hobbies=" + this.hobbies + ")";
        }
    }
}
- 其实,lombok的创作者还是很用心的,在进行build()来创建实例对象时,并没有直接使用Collections.unmodifiableList(Collection)此方法来创建实例,而是分为三种情况:
- 第1种,当集合中没有元素时,创建一个空list
- 第2种,当集合中存在一个元素时,创建一个不可变的单元素list
- 第3种,根据当前集合的元素数量创建对应合适大小的list
当然我们看编译生成的代码,创建了三个关于集合操作的方法:
hobby(String hobby):向集合中添加一个元素
hobbies(Collection<? extends String> hobbies):添加一个集合所有的元素
clearHobbies():清空当前集合数据
@Singular 注解配置value属性
- 先来看看 @Singular注解的详情:
@Target({FIELD, PARAMETER})
@Retention(SOURCE)
public @interface Singular {
    // 修改添加集合元素的方法名
    String value() default "";
}
- 测试如何使用注解属性value
@Builder
public class User {
    private final Integer id;
    private final String zipCode = "123456";
    private String username;
    private String password;
    @Singular(value = "testHobbies")
    private List<String> hobbies;
}
// 测试类
public class BuilderTest {
    public static void main(String[] args) {
        User user = User.builder()
                .testHobbies("reading")
                .testHobbies("eat")
                .id(1)
                .password("admin")
                .username("admin")
                .build();
        System.out.println(user);
    }
}
说明,当我们使用了注解属性value之后,我们在使用添加集合元素时的方法名发生相应的改变。
但是,同时生成的添加整个集合的方法名发生改变了吗?我们再来看看编译后的代码:
// 编译后:
public class User {
    // 省略部分代码,只看关键部分
    public static class UserBuilder {
        public User.UserBuilder testHobbies(String testHobbies) {
            if (this.hobbies == null) {
                this.hobbies = new ArrayList();
            }
            this.hobbies.add(testHobbies);
            return this;
        }
        public User.UserBuilder hobbies(Collection<? extends String> hobbies) {
            if (this.hobbies == null) {
                this.hobbies = new ArrayList();
            }
            this.hobbies.addAll(hobbies);
            return this;
        }
        
        public User.UserBuilder clearHobbies() {
            if (this.hobbies != null) {
                this.hobbies.clear();
            }
            return this;
        }
    }
}
可以看到,只有添加一个元素的方法名发生了改变。
lombok中的@Builder.Default注解
- lombok中的- @Builder.Default注解为成员变量赋默认值
(1)只对成员变量设置默认值,builder构造默认值是无效的
User
import com.alibaba.fastjson2.JSON;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.UUID;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class User {
    private String id = UUID.randomUUID().toString();;
    private final String zipCode = "123456";
    private String username;
    private String password;
    @Singular
    private List<String> hobbies;
}
如果我们用,java的
new操作创建对象,是会对 User 设置默认值的
    public static void main(String[] args) {
        User user = new User();
        User user2 = new User();
        log.info("user:{}", JSON.toJSONString( user ));
        log.info("user2:{}", JSON.toJSONString( user2 ));
    }
out
user:{"id":"c470357e-72e0-4780-b500-22ab1bb115ee","zipCode":"123456"}
user2:{"id":"2879436b-7884-4d57-83c9-17aa52bd0a4e","zipCode":"123456"}
但是
Builder方式创建对象,是无效的
    public static void main(String[] args) {
        User userByBuilder = User.builder().build();
        User userByBuilder2 = User.builder().build();
        log.info("userByBuilder:{}", JSON.toJSONString( userByBuilder ));
        log.info("userByBuilder2:{}", JSON.toJSONString( userByBuilder2 ));
    }
out
user:{"hobbies":[],"zipCode":"123456"}
user2:{"hobbies":[],"zipCode":"123456"}
原因在于,编译生成的
User.class文件,保留了成员变量的初始值,但是在UserBuilder中,只有成员变量,而没有默认值
//编译后:
import com.alibaba.fastjson2.JSON;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class User {
    private static final Logger log = LoggerFactory.getLogger(User.class);
    private String id = UUID.randomUUID().toString();
    private final String zipCode = "123456";
    private String username;
    private String password;
    private List<String> hobbies;
    public static UserBuilder builder() {
        return new UserBuilder();
    }
    public String getId() {
        return this.id;
    }
    public String getZipCode() {
        Objects.requireNonNull(this);
        return "123456";
    }
    public String getUsername() {
        return this.username;
    }
    public String getPassword() {
        return this.password;
    }
    public List<String> getHobbies() {
        return this.hobbies;
    }
    public void setId(String id) {
        this.id = id;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof User)) {
            return false;
        } else {
            User other = (User)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                Object this$id = this.getId();
                Object other$id = other.getId();
                if (this$id == null) {
                    if (other$id != null) {
                        return false;
                    }
                } else if (!this$id.equals(other$id)) {
                    return false;
                }
                Object this$zipCode = this.getZipCode();
                Object other$zipCode = other.getZipCode();
                if (this$zipCode == null) {
                    if (other$zipCode != null) {
                        return false;
                    }
                } else if (!this$zipCode.equals(other$zipCode)) {
                    return false;
                }
                Object this$username = this.getUsername();
                Object other$username = other.getUsername();
                if (this$username == null) {
                    if (other$username != null) {
                        return false;
                    }
                } else if (!this$username.equals(other$username)) {
                    return false;
                }
                Object this$password = this.getPassword();
                Object other$password = other.getPassword();
                if (this$password == null) {
                    if (other$password != null) {
                        return false;
                    }
                } else if (!this$password.equals(other$password)) {
                    return false;
                }
                Object this$hobbies = this.getHobbies();
                Object other$hobbies = other.getHobbies();
                if (this$hobbies == null) {
                    if (other$hobbies != null) {
                        return false;
                    }
                } else if (!this$hobbies.equals(other$hobbies)) {
                    return false;
                }
                return true;
            }
        }
    }
    protected boolean canEqual(Object other) {
        return other instanceof User;
    }
    public int hashCode() {
        int PRIME = 59;
        int result = 1;
        Object $id = this.getId();
        result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $zipCode = this.getZipCode();
        result = result * 59 + ($zipCode == null ? 43 : $zipCode.hashCode());
        Object $username = this.getUsername();
        result = result * 59 + ($username == null ? 43 : $username.hashCode());
        Object $password = this.getPassword();
        result = result * 59 + ($password == null ? 43 : $password.hashCode());
        Object $hobbies = this.getHobbies();
        result = result * 59 + ($hobbies == null ? 43 : $hobbies.hashCode());
        return result;
    }
    public String toString() {
        String var10000 = this.getId();
        return "User(id=" + var10000 + ", zipCode=" + this.getZipCode() + ", username=" + this.getUsername() + ", password=" + this.getPassword() + ", hobbies=" + this.getHobbies() + ")";
    }
    public User() {
    }
    public User(String id, String username, String password, List<String> hobbies) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.hobbies = hobbies;
    }
    public static class UserBuilder {
        private String id;
        private String username;
        private String password;
        private ArrayList<String> hobbies;
        UserBuilder() {
        }
        public UserBuilder id(String id) {
            this.id = id;
            return this;
        }
        public UserBuilder username(String username) {
            this.username = username;
            return this;
        }
        public UserBuilder password(String password) {
            this.password = password;
            return this;
        }
        public UserBuilder hobby(String hobby) {
            if (this.hobbies == null) {
                this.hobbies = new ArrayList();
            }
            this.hobbies.add(hobby);
            return this;
        }
        public UserBuilder hobbies(Collection<? extends String> hobbies) {
            if (hobbies == null) {
                throw new NullPointerException("hobbies cannot be null");
            } else {
                if (this.hobbies == null) {
                    this.hobbies = new ArrayList();
                }
                this.hobbies.addAll(hobbies);
                return this;
            }
        }
        public UserBuilder clearHobbies() {
            if (this.hobbies != null) {
                this.hobbies.clear();
            }
            return this;
        }
        public User build() {
            List<String> hobbies;
            switch (this.hobbies == null ? 0 : this.hobbies.size()) {
                case 0 -> hobbies = Collections.emptyList();
                case 1 -> hobbies = Collections.singletonList((String)this.hobbies.get(0));
                default -> hobbies = Collections.unmodifiableList(new ArrayList(this.hobbies));
            }
            return new User(this.id, this.username, this.password, hobbies);
        }
        public String toString() {
            return "User.UserBuilder(id=" + this.id + ", username=" + this.username + ", password=" + this.password + ", hobbies=" + this.hobbies + ")";
        }
    }
}
(2)设置@Builder.Default注解后,通过标识判断是否启用默认值
User
import com.alibaba.fastjson2.JSON;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.UUID;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class User {
    @Builder.Default
    private String id = UUID.randomUUID().toString();;
    private final String zipCode = "123456";
    private String username;
    private String password;
    @Singular
    private List<String> hobbies;
}
测试
public static void main(String[] args) {
	User user = new User();
	User user2 = new User();
	log.info("user:{}", JSON.toJSONString( user ));
	log.info("user2:{}", JSON.toJSONString( user2 ));
	User userByBuilder = User.builder().build();
	User userByBuilder2 = User.builder().build();
	log.info("userByBuilder:{}", JSON.toJSONString( userByBuilder ));
	log.info("userByBuilder2:{}", JSON.toJSONString( userByBuilder2 ));
}
运行结果:
user:{"id":"4e54f5e9-d131-4fe7-a139-80a4b7a24f7c","zipCode":"123456"}
user2:{"id":"a674bbd5-79af-48e7-8576-d96df5b82c01","zipCode":"123456"}
userByBuilder:{"hobbies":[],"id":"b121eded-b369-407a-bc21-6ab994550a05","zipCode":"123456"}
userByBuilder2:{"hobbies":[],"id":"b26b3314-d778-40ef-866d-dd7f181e0025","zipCode":"123456"}
User 编译后:
import com.alibaba.fastjson2.JSON;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class User {
    private static final Logger log = LoggerFactory.getLogger(User.class);
    private String id;
    private final String zipCode = "123456";
    private String username;
    private String password;
    private List<String> hobbies;
    private static String $default$id() {
        return UUID.randomUUID().toString();
    }
    public static UserBuilder builder() {
        return new UserBuilder();
    }
    public String getId() {
        return this.id;
    }
    public String getZipCode() {
        Objects.requireNonNull(this);
        return "123456";
    }
    public String getUsername() {
        return this.username;
    }
    public String getPassword() {
        return this.password;
    }
    public List<String> getHobbies() {
        return this.hobbies;
    }
    public void setId(String id) {
        this.id = id;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof User)) {
            return false;
        } else {
            User other = (User)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                Object this$id = this.getId();
                Object other$id = other.getId();
                if (this$id == null) {
                    if (other$id != null) {
                        return false;
                    }
                } else if (!this$id.equals(other$id)) {
                    return false;
                }
                Object this$zipCode = this.getZipCode();
                Object other$zipCode = other.getZipCode();
                if (this$zipCode == null) {
                    if (other$zipCode != null) {
                        return false;
                    }
                } else if (!this$zipCode.equals(other$zipCode)) {
                    return false;
                }
                Object this$username = this.getUsername();
                Object other$username = other.getUsername();
                if (this$username == null) {
                    if (other$username != null) {
                        return false;
                    }
                } else if (!this$username.equals(other$username)) {
                    return false;
                }
                Object this$password = this.getPassword();
                Object other$password = other.getPassword();
                if (this$password == null) {
                    if (other$password != null) {
                        return false;
                    }
                } else if (!this$password.equals(other$password)) {
                    return false;
                }
                Object this$hobbies = this.getHobbies();
                Object other$hobbies = other.getHobbies();
                if (this$hobbies == null) {
                    if (other$hobbies != null) {
                        return false;
                    }
                } else if (!this$hobbies.equals(other$hobbies)) {
                    return false;
                }
                return true;
            }
        }
    }
    protected boolean canEqual(Object other) {
        return other instanceof User;
    }
    public int hashCode() {
        int PRIME = 59;
        int result = 1;
        Object $id = this.getId();
        result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $zipCode = this.getZipCode();
        result = result * 59 + ($zipCode == null ? 43 : $zipCode.hashCode());
        Object $username = this.getUsername();
        result = result * 59 + ($username == null ? 43 : $username.hashCode());
        Object $password = this.getPassword();
        result = result * 59 + ($password == null ? 43 : $password.hashCode());
        Object $hobbies = this.getHobbies();
        result = result * 59 + ($hobbies == null ? 43 : $hobbies.hashCode());
        return result;
    }
    public String toString() {
        String var10000 = this.getId();
        return "User(id=" + var10000 + ", zipCode=" + this.getZipCode() + ", username=" + this.getUsername() + ", password=" + this.getPassword() + ", hobbies=" + this.getHobbies() + ")";
    }
    public User() {
        this.id = $default$id();
    }
    public User(String id, String username, String password, List<String> hobbies) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.hobbies = hobbies;
    }
    public static class UserBuilder {
        private boolean id$set;
        private String id$value;
        private String username;
        private String password;
        private ArrayList<String> hobbies;
        UserBuilder() {
        }
        public UserBuilder id(String id) {
            this.id$value = id;
            this.id$set = true;
            return this;
        }
        public UserBuilder username(String username) {
            this.username = username;
            return this;
        }
        public UserBuilder password(String password) {
            this.password = password;
            return this;
        }
        public UserBuilder hobby(String hobby) {
            if (this.hobbies == null) {
                this.hobbies = new ArrayList();
            }
            this.hobbies.add(hobby);
            return this;
        }
        public UserBuilder hobbies(Collection<? extends String> hobbies) {
            if (hobbies == null) {
                throw new NullPointerException("hobbies cannot be null");
            } else {
                if (this.hobbies == null) {
                    this.hobbies = new ArrayList();
                }
                this.hobbies.addAll(hobbies);
                return this;
            }
        }
        public UserBuilder clearHobbies() {
            if (this.hobbies != null) {
                this.hobbies.clear();
            }
            return this;
        }
        public User build() {
            List<String> hobbies;
            switch (this.hobbies == null ? 0 : this.hobbies.size()) {
                case 0 -> hobbies = Collections.emptyList();
                case 1 -> hobbies = Collections.singletonList((String)this.hobbies.get(0));
                default -> hobbies = Collections.unmodifiableList(new ArrayList(this.hobbies));
            }
            String id$value = this.id$value;
            if (!this.id$set) {
                id$value = User.$default$id();
            }
            return new User(id$value, this.username, this.password, hobbies);
        }
        public String toString() {
            return "User.UserBuilder(id$value=" + this.id$value + ", username=" + this.username + ", password=" + this.password + ", hobbies=" + this.hobbies + ")";
        }
    }
}
@Builder 全局配置
# 是否禁止使用@Builder
lombok.builder.flagUsage = [warning | error] (default: not set)
# 是否使用Guaua
lombok.singular.useGuava = [true | false] (default: false)
# 是否自动使用singular,默认是使用
lombok.singular.auto = [true | false] (default: true)
参考文献
Y FAQ for 建造者模式
Q: 与工厂模式的区别?
- 与工厂模式的区别是:建造者模式更加关注于零件装配的顺序。
Y 推荐文献
X 参考文献
 
    本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号