将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
抽象建造者类(builder):为创建product对象而指定各个组件的抽象接口
具体建造类(concreteBuilder):实现builder接口,重写方法构建不同的表示
产品类(product):具体的产品
指挥者类(director):构建一个使用builder接口的对象
1.创建的对象比较复杂 2.需要生成的对象内部属性本身相互依赖
以建造人为例,分为建造瘦子和胖子,它们的步骤都是先造头,再造身体,其次胳膊,最后腿,然而他俩的区别是具体建造类的实现不同
Person类
package com.headfirst.buildermode.dao;
public class Person {
public String head;
public String body;
public String arms;
public String legs;
public String getHead() {
return head;
}
public void setHead(String head) {
this.head = head;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getArms() {
return arms;
}
public void setArms(String arms) {
this.arms = arms;
}
public String getLegs() {
return legs;
}
public void setLegs(String legs) {
this.legs = legs;
}
@Override
public String toString() {
return this.getHead()+this.getBody()+this.getArms()+this.getLegs();
}
}
建造者抽象类
package com.headfirst.buildermode.interfaces;
import com.headfirst.buildermode.dao.Person;
/**
* 定义了具体实现类的抽象接口
* 1.建造不同的人(胖子和瘦子)
* 2.建造者模式是类创建型的模式
*/
public interface IBuilder {
public abstract void createHead();
public abstract void createBody();
public abstract void createArms();
public abstract void createLegs();
public abstract Person buildPerson();
}
(瘦子)具体建造者类
package com.headfirst.buildermode.dao;
import com.headfirst.buildermode.interfaces.IBuilder;
public class ThinPersonBuilder implements IBuilder {
private Person person = null;
public ThinPersonBuilder() {
if(person == null){
person = new Person();
}
}
@Override
public void createHead() {
person.setHead("我");
}
@Override
public void createBody() {
person.setBody("是");
}
@Override
public void createArms() {
person.setArms("瘦");
}
@Override
public void createLegs() {
person.setLegs("子");
}
@Override
public Person buildPerson() {
return person;
}
}
(胖子)具体建造类
package com.headfirst.buildermode.dao;
import com.headfirst.buildermode.interfaces.IBuilder;
public class FatPersonBuilder implements IBuilder {
private Person person = null;
public FatPersonBuilder() {
if(person == null){
person = new Person();
}
}
@Override
public void createHead() {
person.setHead("我");
}
@Override
public void createBody() {
person.setBody("是");
}
@Override
public void createArms() {
person.setArms("胖");
}
@Override
public void createLegs() {
person.setLegs("子");
}
@Override
public Person buildPerson() {
return person;
}
}
指挥者类
package com.headfirst.buildermode.dao;
import com.headfirst.buildermode.interfaces.IBuilder;
public class BuilderDirector {
private IBuilder ibuilder = null;
public BuilderDirector(IBuilder ib){
if(ibuilder == null){
ibuilder = ib;
}
}
public Person buildPerson(){
ibuilder.createHead();
ibuilder.createBody();
ibuilder.createArms();
ibuilder.createLegs();
return ibuilder.buildPerson();
}
}
测试类
public static void main(String[] args) {
ThinPersonBuilder thinPersonBuilder = new ThinPersonBuilder();
BuilderDirector director = new BuilderDirector(thinPersonBuilder);
Person thinPerson = director.buildPerson();
System.out.println(thinPerson.toString());
FatPersonBuilder fatPersonBuilder = new FatPersonBuilder();
BuilderDirector director2 = new BuilderDirector(fatPersonBuilder);
Person fatPerson = director2.buildPerson();
System.out.println(fatPerson.toString());
}
测试结果
1.将创建代码和表示代码分离,有利于解耦合
2.当需要增加新的功能时,只需要增加一个新的类,符合开闭原则
受限于产品必须有共同点,否则不适用建造者模式
java.lang.StringBuilder#append(Character c)
由上图我们可以看出StringBuilder继承了AbstractStringBuilder,而AbstractStringBuilder实现了appendable。
StringBuilder:指挥者类,持有具体建造者的引用,由于StringBuilder继承了AbstractStringBuilder,这里StringBuilder通过super来作为具体建造者的引用。
AbstractStringBuilder:具体建造者,它实现了appendable接口的append(Character c)方法。
appendable:抽象建造者,定义了创建对象的接口。
StringBuilder的append(Character c)方法:
/**
*/
public StringBuilder append(CharSequence s) {
if (s == null)
s = "null";
if (s instanceof String)
return this.append((String)s);
if (s instanceof StringBuffer)
return this.append((StringBuffer)s);
if (s instanceof StringBuilder)
return this.append((StringBuilder)s);
return this.append(s, 0, s.length());
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public StringBuilder append(CharSequence s, int start, int end) {
//调用具体建造者的append方法
super.append(s, start, end);
return this;
}
AbstractStringBuilder的append(CharSequence s, int start, int end) 方法:
public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
s = "null";
if ((start < 0) || (start > end) || (end > s.length()))
throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", s.length() "
+ s.length());
int len = end - start;
ensureCapacityInternal(count + len);
for (int i = start, j = count; i < end; i++, j++)
value[j] = s.charAt(i);
count += len;
return this;
}
appendable抽象建造者:
/**
* An object to which char sequences and values can be appended. The
* Appendable interface must be implemented by any class whose
* instances are intended to receive formatted output from a {@link
* java.util.Formatter}.
*
* The characters to be appended should be valid Unicode characters as
* described in Unicode Character
* Representation. Note that supplementary characters may be composed of
* multiple 16-bit char values.
*
*
Appendables are not necessarily safe for multithreaded access. Thread
* safety is the responsibility of classes that extend and implement this
* interface.
*
*
Since this interface may be implemented by existing classes
* with different styles of error handling there is no guarantee that
* errors will be propagated to the invoker.
*
* @since 1.5
*/
public interface Appendable {
/**
* Appends the specified character sequence to this Appendable.
*
*
Depending on which class implements the character sequence
* csq, the entire sequence may not be appended. For
* instance, if csq is a {@link java.nio.CharBuffer} then
* the subsequence to append is defined by the buffer's position and limit.
*
* @param csq
* The character sequence to append. If csq is
* null, then the four characters "null" are
* appended to this Appendable.
*
* @return A reference to this Appendable
*
* @throws IOException
* If an I/O error occurs
*/
Appendable append(CharSequence csq) throws IOException;
/**
* Appends a subsequence of the specified character sequence to this
* Appendable.
*
*
An invocation of this method of the form out.append(csq, start,
* end) when csq is not null, behaves in
* exactly the same way as the invocation
*
*
* out.append(csq.subSequence(start, end))
*
* @param csq
* The character sequence from which a subsequence will be
* appended. If csq is null, then characters
* will be appended as if csq contained the four
* characters "null".
*
* @param start
* The index of the first character in the subsequence
*
* @param end
* The index of the character following the last character in the
* subsequence
*
* @return A reference to this Appendable
*
* @throws IndexOutOfBoundsException
* If start or end are negative, start
* is greater than end, or end is greater than
* csq.length()
*
* @throws IOException
* If an I/O error occurs
*/
Appendable append(CharSequence csq, int start, int end) throws IOException;
/**
* Appends the specified character to this Appendable.
*
* @param c
* The character to append
*
* @return A reference to this Appendable
*
* @throws IOException
* If an I/O error occurs
*/
Appendable append(char c) throws IOException;
}
java.lang.StringBuffer#append(Character c)
StringBuffer本质上和StringBuilder是一样的,唯一的区别就是StringBuffer的append方法上加了synchronized,所以StringBuffer是线程安全的,而StringBuilder不是线程安全的。
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @since 1.5
*/
public synchronized StringBuffer append(CharSequence s, int start, int end)
{
super.append(s, start, end);
return this;
}
public synchronized StringBuffer append(char[] str) {
super.append(str);
return this;
}