[设计模式/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 类,带有 ItemArrayList 和一个通过结合 Item 来创建不同类型的 Meal 对象的 MealBuilderBuilderPatternDemo 类使用 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 参考文献

posted @ 2025-04-05 15:57  千千寰宇  阅读(60)  评论(0)    收藏  举报