然建造者模式是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
特征:用户只需指定需要建造的类型就可以获得对象,建造过程及细节不需要了解。
适用场景
适用于创建对象需要很多步骤,但是步骤的顺序不一定固定。
如果一个对象有非常复杂的内部结构(很多属性)
把复杂对象的创建和使用分离。
示例:
创建一个课程类
@Data
public class Course {
private String name;
private String ppt;
private String video;
private String note;
}
创建一个builder对象构建课程对象,每个add方法都返回builder对象自己。提供一个builder方法返回课程对象。
public class CourseBuilder {
private Course course = new Course();
public CourseBuilder addName(String name){
course.setName(name);
return this;
}
public CourseBuilder addPpt(String ppt){
course.setPpt(ppt);
return this;
}
public CourseBuilder addVideo(String video){
course.setVideo(video);
return this;
}
public CourseBuilder addNote(String note){
course.setNote(note);
return this;
}
public Course builder(){
return course;
}
}
链式编程的方式很优雅的构建课程对象
public class Test {
public static void main(String[] args){
CourseBuilder courseBuilder = new CourseBuilder();
courseBuilder.addName("java")
.addNote("笔记")
.addPpt("ppt课件")
.addVideo("video");
System.out.println(courseBuilder.builder());
}
}
建造者模式的应用
StringBuilder
/**
* Constructs a string builder with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuilder() {
super(16);
}
/**
* Constructs a string builder with no characters in it and an
* initial capacity specified by the {@code capacity} argument.
*
* @param capacity the initial capacity.
* @throws NegativeArraySizeException if the {@code capacity}
* argument is less than {@code 0}.
*/
public StringBuilder(int capacity) {
super(capacity);
}
/**
* Constructs a string builder initialized to the contents of the
* specified string. The initial capacity of the string builder is
* {@code 16} plus the length of the string argument.
*
* @param str the initial contents of the buffer.
*/
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
/**
* Constructs a string builder that contains the same characters
* as the specified {@code CharSequence}. The initial capacity of
* the string builder is {@code 16} plus the length of the
* {@code CharSequence} argument.
*
* @param seq the sequence to copy.
*/
public StringBuilder(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
提供4个构造方法,默认构造一个长度为16的char数组,也可以指定容量,如果传入String或者CharSequence会构造一个长度加16的char数组再调用append方法。父类构造方法如下:
/**
* Creates an AbstractStringBuilder of the specified capacity.
*/
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
然后提供了很多append方法接受各种参数的,很多都是直接调用父类的append方法完成。
public StringBuilder append(StringBuffer sb) {
super.append(sb);
return this;
}
@Override
public StringBuilder append(CharSequence s) {
super.append(s);
return this;
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuilder append(CharSequence s, int start, int end) {
super.append(s, start, end);
return this;
}
@Override
public StringBuilder append(char[] str) {
super.append(str);
return this;
}
最后在toString方法new一个String对象返回
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
还有比如CacheBuilder,SqlSessionFactoryBuilder,BeanDefinitionBuilder等等都是建造者模式。
建造者模式的优点
封装性好,创建和使用分离
扩展性好,建造类之间独立,一定程度上解耦
建造者模式的缺点
产生多余的builder对象
产品内部发生变化,建造者也要修改,成本较大
建造者模式跟工厂模式的区别
1.建造者模式更加注重方法的调用顺序,工厂模式注重于创建对象。
2.创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的都一样。
3.关注点:工厂模式只需要把对象创建出来就可以了,而建造者模式中不仅要创建出这个对象,还要知道这个对象由哪些部件组成。
4.建造者模式根据建造过程中的顺序不一样,最终的对象部件组成也不一样。