創建型模式【4】——建造者模式

 


1 建造者模式特點

  • 定義 : 將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示
  • 特點 : 用戶只需指定需要建造的類型就可以得到它們,建造過程及細節不需要知道
  • 類型 : 創建型

 適用場景

  • 如果一個對象有非常複雜的內部結構(很多屬性)
  • 想把複雜對象的創建和使用分離
  • 優點 : 封裝性好,創建和使用分離;擴展性好,建造類之間獨立,一定程度上解耦
  • 缺點 :  產生多餘的Builder對象;產品內部發生變化,建造者都要修改,成本較大

建造者模式 vs 工廠模式 : 建造者模式更注重於方法的調用順序,工廠模式注重於創建產品;創建對象的粒度不同,建造者模式可以創建複雜的產品,由各種複雜的部件組成,工廠模式創建出來的都是一個樣子;關注點不同,工廠模式注重的是只需要把對象創建出來就ok,建造者模式不只要創建出這個產品,還要知道產品是由那些部件組成的,有些場景還需要關注各個部件的順序


2 Coding 

public class Course {
    //課程名
    private String courseName;
    //課程需要的PPT
    private String coursePPT;
    //課程需要的視頻
    private String courseVideo;
    //課程的手記
    private String courseArticle;
    //question & answer
    private String courseQA;
    //省略 get set toString 
}
public abstract class CourseBuilder {
    public abstract void buildCourseName(String courseName);
    public abstract void buildCoursePPT(String coursePPT);
    public abstract void buildCourseVideo(String courseVideo);
    public abstract void buildCourseArticle(String courseArticle);
    public abstract void buildCourseQA(String courseQA);
    public abstract Course makeCourse();
}
public class CourseActualBuilder extends CourseBuilder {
    private Course course = new Course();
    @Override
    public void buildCourseName(String courseName) {
        course.setCourseName(courseName);
    }
    @Override
    public void buildCoursePPT(String coursePPT) {
        course.setCoursePPT(coursePPT);
    }
    @Override
    public void buildCourseVideo(String courseVideo) {
        course.setCourseVideo(courseVideo);
    }
    @Override
    public void buildCourseArticle(String courseArticle) {
        course.setCourseArticle(courseArticle);
    }
    @Override
    public void buildCourseQA(String courseQA) {
        course.setCourseQA(courseQA);
    }
    @Override
    public Course makeCourse() {
        return course;
    }
}
public class Coach {
    private CourseBuilder courseBuilder;
    public void setCourseBuilder(CourseBuilder courseBuilder) {
        this.courseBuilder = courseBuilder;
    }
    public Course makeCourse(String courseName, String coursePPT, String courseVideo, String courseArticle, String courseQA) {
        this.courseBuilder.buildCourseName(courseName);
        this.courseBuilder.buildCoursePPT(coursePPT);
        this.courseBuilder.buildCourseVideo(courseVideo);
        this.courseBuilder.buildCourseArticle(courseArticle);
        this.courseBuilder.buildCourseQA(courseQA);
        return this.courseBuilder.makeCourse();
    }
}
public class CourseTest {
    @Test
    public void test() {
        CourseBuilder courseBuilder = new CourseActualBuilder();
        Coach coach = new Coach();
        coach.setCourseBuilder(courseBuilder);
        Course course = coach.makeCourse("Java設計模式精講",
                "Java設計模式精講PPT",
                "Java設計模式精講視頻",
                "Java設計模式精講手記",
                "Java設計模式精講問答");
        System.out.println(course);
    }
}

 

public class Course {
    private String courseName;
    private String coursePPT;
    private String courseVideo;
    private String courseArticle;
    //question & answer
    private String courseQA;
    public Course(CourseBuilder courseBuilder) {
        this.courseName = courseBuilder.courseName;
        this.coursePPT = courseBuilder.coursePPT;
        this.courseVideo = courseBuilder.courseVideo;
        this.courseArticle = courseBuilder.courseArticle;
        this.courseQA = courseBuilder.courseQA;
    }
    //內部類
    public static class CourseBuilder {
        private String courseName;
        private String coursePPT;
        private String courseVideo;
        private String courseArticle;
        private String courseQA;
        public CourseBuilder buildCourseName(String courseName) {
            this.courseName = courseName;
            //返回的是本身
            return this;
        }
        public CourseBuilder buildCoursePPT(String coursePPT) {
            this.coursePPT = coursePPT;
            return this;
        }
        public CourseBuilder buildCourseVideo(String courseVideo) {
            this.courseVideo = courseVideo;
            return this;
        }
        public CourseBuilder buildCourseArticle(String courseArticle) {
            this.courseArticle = courseArticle;
            return this;
        }
        public CourseBuilder buildCourseQA(String courseQA) {
            this.courseQA = courseQA;
            return this;
        }
        public Course build() {
            return new Course(this);
        }
    }
    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                ", coursePPT='" + coursePPT + '\'' +
                ", courseVideo='" + courseVideo + '\'' +
                ", courseArticle='" + courseArticle + '\'' +
                ", courseQA='" + courseQA + '\'' +
                '}';
    }
}
public class CourseTest {
    @Test
    public void test() {
        Course course = new Course.CourseBuilder()
                .buildCourseName("Java設計模式精講")
                .buildCoursePPT("Java設計模式精講PPT")
                .buildCourseVideo("Java設計模式精講視頻")
                .build();
        System.out.println(course);
    }
}


3 靜態內部類特點

//外部類
public class Out {
    //靜態內部類
    public static class In {
        private int age;
    }
}
public class Main {
    public static void main(String[] args) {
        Out.In a = new Out.In();
        System.out.println(System.identityHashCode(a)); //1878246837
        Out.In b = new Out.In();
        System.out.println(System.identityHashCode(b)); //929338653
    }
}

4 源碼分析

//java.lang.StringBuilder
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
    //StringBuffer也是一樣,就是多了一個synchronized
	@Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
//<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
//<dependency>
//    <groupId>com.google.guava</groupId>
//    <artifactId>guava</artifactId>
//    <version>29.0-jre</version>
//</dependency>
@Test
public void test() {
    //com.google.common.collect.ImmutableSet
    Set<String> set = ImmutableSet.<String>builder()
            .add("a")
            .add("b")
            .build();
    System.out.println(set); //[a, b]
    //com.google.common.cache.CacheBuilder

    LoadingCache<String, String> localCache = CacheBuilder.newBuilder()
            .initialCapacity(1000) //cache初始化大小
            .maximumSize(10000) //cache的最大容量
            .expireAfterAccess(12, TimeUnit.HOURS)//有效期
            .concurrencyLevel(5) //併發數
            .build(
                    new CacheLoader<String, String>() {
                        @Override
                        public String load(String s) {
                            return "null";
                        }
                    }
            );
}
//org.springframework.beans.factory.support.BeanDefinitionBuilder
public final class BeanDefinitionBuilder {
    //注意方法的返回值是當前對象
    public BeanDefinitionBuilder setFactoryMethod(String factoryMethod) {
        this.beanDefinition.setFactoryMethodName(factoryMethod);
        return this;
    }
@SpringBootApplication
public class VxVideoApplication {
    public static void main(String[] args) {
       new SpringApplicationBuilder(VxVideoApplication.class)
               .web(WebApplicationType.SERVLET)
               //還可以設置其他...
               .run(args);
    }
}
//<dependency>
//    <groupId>org.mybatis</groupId>
//    <artifactId>mybatis</artifactId>
//    <version>3.5.4</version>
//</dependency>

//org.apache.ibatis.session.SqlSessionFactoryBuilder
public class SqlSessionFactoryBuilder {
  //裏面再次使用建造者模式
  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
//<dependency>
//    <groupId>org.projectlombok</groupId>
//    <artifactId>lombok</artifactId>
//    <version>1.18.12</version>
//</dependency>
@Builder //lombok.Builder
public class User {
    /**主鍵ID*/
    private Long id;
    /**用戶名*/
    private String userName;
    /**密碼*/
    private String password;
    /**姓名*/
    private String name;
    /**年齡*/
    private Integer age;
    /**郵箱*/
    private String email;
}
//生產的class如下
public class User {
    private Long id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
    User(Long id, String userName, String password, String name, Integer age, String email) {
        this.id = id;
        this.userName = userName;
        this.password = password;
        this.name = name;
        this.age = age;
        this.email = email;
    }
    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }
    public static class UserBuilder {
        private Long id;
        private String userName;
        private String password;
        private String name;
        private Integer age;
        private String email;
        UserBuilder(){}
        public User.UserBuilder id(Long 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 name(String name) {
            this.name = name;
            return this;
        }
        public User.UserBuilder age(Integer age) {
            this.age = age;
            return this;
        }
        public User.UserBuilder email(String email) {
            this.email = email;
            return this;
        }
        public User build() {
            return new User(this.id, this.userName, this.password, this.name, this.age, this.email);
        }
        public String toString() {
            return "User.UserBuilder(id=" + this.id + ", userName=" + this.userName + ", password=" + this.password + ", name=" + this.name + ", age=" + this.age + ", email=" + this.email + ")";
        }
    }
}
//調用
@Test
public void test() {
    User user = User.builder()
            .name("喬碧蘿")
            .age(58)
            .build();
    System.out.println(user); //User@61e717c2
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章