zoukankan      html  css  js  c++  java
  • 设计模式-Builder模式详解

    Builder模式详解

    Builder模式也叫做建造者模式,是设计模式的一种,
    就是将复杂对象的创建变得简单明了,使对象与他的表示进行分离,使得同样的创建过程,可以创建不同的对象.

    我们这里讲变种 Builder模式(更加简单,明了),并非真正意义上的Builder模式;这种模式的目的用于简化(不可变)对象的构造(比如 Google 的 Protobuf 协议,在生成为 Java 代码后,都会提供一个 Builder 类去构造相关 Message)

    Builder模式作用

    解决让Object始终保持valid状态的问题,解决具有大量参数的构造函数不好用的问题
    先看普通构建User类:

    public class User {
    
      private String name;
    
      private String password;
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        this.name = name;
      }
    
      public String getPassword() {
        return password;
      }
    
      public void setPassword(String password) {
        this.password = password;
      }
    
      public String toString() {
        return "User(name=" + this.getName() + ", password=" + this.getPassword() + ")";
      }
    
    }
    
    

    Builder模式:

    public class UserB {
    
      private final String name;
    
      private final String password;
    
      public UserB(UserB.UserBuilder builder) {
        this.name = builder.name;
        this.password = builder.password;
      }
    
      public String getName() {
        return name;
      }
    
      public String getPassword() {
        return password;
      }
    
      public static final class UserBuilder {
        private final String name;
        private String password;
    
        private UserBuilder(String names) {
          this.name = names;
        }
          public String toString() {
        return "User(name=" + this.getName() + ", password=" + this.getPassword() + ")";
      }
    
    
        //构建参数是必传参数
        public static UserB.UserBuilder create(String name) {
          return new UserB.UserBuilder(name);
        }
    
        public UserB.UserBuilder withPassword(String password) {
          this.password = password;
          return this;
        }
    
        public UserB build() {
          return new UserB(this);
        }
      }
    
    
    }
    

    这种传统的方式创建大家用的比较多,但是有很多缺点,如我要同时创建多个User,然后对应的User部分属性不一样,这样我要一个一个new就很麻烦,但是使用Builder模式就简单一点:

    对应的main测试:

    public static void main(String[] args) {
        User user = new User();
        user.setName("aaa");
        user.setPassword("123");
        System.out.println(user.toString());
    
        UserB.UserBuilder aaa = UserB.UserBuilder.create("aaa");
        aaa.withPassword("123");
    
        UserB build = aaa.build();
        aaa.withPassword("456");
        UserB build1 = aaa.build();
        aaa.withPassword("111");
        UserB build2 = aaa.build();
        System.out.println(build);
        System.out.println(build1);
        System.out.println(build2);
    
      }
    

    生成的Build1,build2是不同的…
    通过new生成的对象,在进行set属性的时候,对象的构造过程是非连续的,也就是说对象可处于一个构造不完全的状态,我们很容易写出将对象传入各个方法,每个方法去赋值对象的某一部分这样的代码,这其实引入了一个状态空间,如果状态空间是强可控的,那还好(但依然提高了维护成本,你需要牢牢掌握住对象的构造过程,什么字段在何处被赋值);如果不可控,那么就很难保证这个对象是否被正确的构造,可能在某个方法中覆盖了某字段,也可能遗漏了某字段导致 NPE。java编程现在都往不可变对象走,就像String类.

    Builder模式创建

    一般都是在User类里面新建静态内部UserBuilder 类并且提供静态create方法返回Builder,然后就是属性方法,返回Builder,最后就是Build方法,返回对应的实体类.
    对应的create方法一般是必传字段,这时候就可以设置为final的;而实体类里面属性就都是final的;

    这种Builder模式几乎都差不多,如果实体类很多的话,我们会写很多重复的代码,这时候就很麻烦,推荐使用Lombok的 @Builder 注解,我们就不需要写任何代码了,我们看看通过@Builder注解生成的Builder类:
    使用:

    @Builder
    @Data
    public class UserLombok {
    
      private final String name;
    
      private final String password;
    
      public static void main(String[] args) {
        UserLombok.UserLombokBuilder build = new UserLombokBuilder().name("aa").password("aa");
        UserLombok build1 = build.build();
        UserLombok build2 = build.build();
        System.out.println(build.name);
      }
    
    }
    

    这里是对应的字节码,反编译的class类:

    
    public class UserLombok {
      private final String name;
      private final String password;
    
      public static void main(String[] args) {
        UserLombok.UserLombokBuilder build = (new UserLombok.UserLombokBuilder()).name("aa").password("aa");
        UserLombok build1 = build.build();
        UserLombok build2 = build.build();
        System.out.println(build.name);
      }
    
      UserLombok(String name, String password) {
        this.name = name;
        this.password = password;
      }
    
      public static UserLombok.UserLombokBuilder builder() {
        return new UserLombok.UserLombokBuilder();
      }
    
      public String getName() {
        return this.name;
      }
    
      public String getPassword() {
        return this.password;
      }
    
        public String toString() {
        return "UserLombok(name=" + this.getName() + ", password=" + this.getPassword() + ")";
      }
    
      public static class UserLombokBuilder {
        private String name;
        private String password;
    
        UserLombokBuilder() {
        }
    
        public UserLombok.UserLombokBuilder name(String name) {
          this.name = name;
          return this;
        }
    
        public UserLombok.UserLombokBuilder password(String password) {
          this.password = password;
          return this;
        }
    
        public UserLombok build() {
          return new UserLombok(this.name, this.password);
        }
    
        public String toString() {
          return "UserLombok.UserLombokBuilder(name=" + this.name + ", password=" + this.password + ")";
        }
      }
    }
    

    同样,如果公司不推荐使用lombok的话,也可以使用idea 的Builder插件来生成部分代码,具体还得看公司的情况,统一才是王道…

    世界上所有的不公平都是由于当事人能力不足造成的.
  • 相关阅读:
    第九周作业
    2020软件工程作业02
    自我介绍
    Java学习开发第三阶段总结
    Java学习开发第一阶段总结
    2019春总结作业
    基础作业
    2019春第四次课程设计实验报告
    2019春第三次课程设计实验报告
    2019春第二次课程设计实验报告
  • 原文地址:https://www.cnblogs.com/javayida/p/13346750.html
Copyright © 2011-2022 走看看