1️⃣概念
定义:讲一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示;
特征:用户只需指定建造的类型就可以得到他们,建造过程及细节不需要知道;
类型:创建型
2️⃣适用场景
如果一个对象有非常复杂的内部结构(例如有很多属性);
想把复杂对象的创建和使用分离;
3️⃣优点
封装性好,创建和使用分离;
扩展性好,建造类之间独立,一定程度上解耦;
4️⃣缺点
产生多余的Builder对象;
产品内部发生变化,建造者都要修改,成本较大;
5️⃣建造者模式与工厂模式的区别
建造者模式注重于方法的调用顺序而工厂模式注重于创建产品;
创建对象的粒度不同:建造者模式可以创建一些复杂的产品,由各种复杂的部件组成;工厂模式创建出来的对象都是一个样子的;
关注点不同:工厂模式关注的是主要把这个对象创建出来就OK了,建造者模式创建产品的时候还需要知道创建出的这个产品是由哪些部件组成的;
6️⃣建造者模式Coding
①我们以攒电脑为例,首先我们声明一个抽象的Builder类
public abstract class Builder {
public abstract void buildCPU(String cpu);
public abstract void buildMainBoard(String mainBoard);
public abstract void buildHardDisk(String hardDisk);
public abstract void buildDisplayCard(String displayCard);
public abstract void buildPower(String power);
public abstract void buildMemory(String memory);
public abstract Computer createComputer();
}
②然后声明一个电脑实体类Computer
public class Computer {
private String cpu;
private String mainBoard;
private String hardDisk;
private String displayCard;
private String power;
private String memory;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getMainBoard() {
return mainBoard;
}
public void setMainBoard(String mainBoard) {
this.mainBoard = mainBoard;
}
public String getHardDisk() {
return hardDisk;
}
public void setHardDisk(String hardDisk) {
this.hardDisk = hardDisk;
}
public String getDisplayCard() {
return displayCard;
}
public void setDisplayCard(String displayCard) {
this.displayCard = displayCard;
}
public String getPower() {
return power;
}
public void setPower(String power) {
this.power = power;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", mainBoard='" + mainBoard + '\'' +
", hardDisk='" + hardDisk + '\'' +
", displayCard='" + displayCard + '\'' +
", power='" + power + '\'' +
", memory='" + memory + '\'' +
'}';
}
}
③声明一个ActualBuilder类来继承Builder
public class ActualBuilder extends Builder {
private Computer computer = new Computer();
@Override
public void buildCPU(String cpu) {
computer.setCpu(cpu);
}
@Override
public void buildMainBoard(String mainBoard) {
computer.setMainBoard(mainBoard);
}
@Override
public void buildHardDisk(String hardDisk) {
computer.setHardDisk(hardDisk);
}
@Override
public void buildDisplayCard(String displayCard) {
computer.setDisplayCard(displayCard);
}
@Override
public void buildPower(String power) {
computer.setPower(power);
}
@Override
public void buildMemory(String memory) {
computer.setMemory(memory);
}
@Override
public Computer createComputer() {
return computer;
}
}
④创建一个DirectorBoss类
public class DirectorBoss {
private Builder builder;
public void setBuilder(Builder builder) {
this.builder = builder;
}
public Computer createComputer(String cpu,String mainBoard,
String hardDisk,String displayCard,
String power,String memory){
this.builder.buildCPU(cpu);
this.builder.buildMainBoard(mainBoard);
this.builder.buildHardDisk(hardDisk);
this.builder.buildDisplayCard(displayCard);
this.builder.buildPower(power);
this.builder.buildMemory(memory);
return this.builder.createComputer();
}
}
⑤创建测试类
public class Test {
public static void main(String[] args) {
Builder builder = new ActualBuilder();
DirectorBoss directorBoss = new DirectorBoss();
directorBoss.setBuilder(builder);
Computer computer = directorBoss.createComputer("酷睿I7","华硕主板","希捷2T硬盘","英伟达显卡","长城电源","威刚内存条8G");
System.out.println(computer);
}
}
⑥UML类图
7️⃣建造者Coding演进
以上的Coding实例,存在一些缺陷,首先DirectorBoss并不是必需的,另外createComputer方法的入参较多很容易出错,所以我们对建造者的实例进行演进;
①创建Computer
public class Computer {
private String cpu;
private String mainBoard;
private String hardDisk;
private String displayCard;
private String power;
private String memory;
public Computer(ComputerBuilder computerBuilder){
this.cpu = computerBuilder.cpu;
this.mainBoard = computerBuilder.mainBoard;
this.hardDisk = computerBuilder.hardDisk;
this.displayCard = computerBuilder.displayCard;
this.power = computerBuilder.power;
this.memory = computerBuilder.memory;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", mainBoard='" + mainBoard + '\'' +
", hardDisk='" + hardDisk + '\'' +
", displayCard='" + displayCard + '\'' +
", power='" + power + '\'' +
", memory='" + memory + '\'' +
'}';
}
public static class ComputerBuilder{
private String cpu;
private String mainBoard;
private String hardDisk;
private String displayCard;
private String power;
private String memory;
public ComputerBuilder buildCPU(String cpu){
this.cpu = cpu;
return this;
}
public ComputerBuilder buildMainBoard(String mainBoard){
this.mainBoard = mainBoard;
return this;
}
public ComputerBuilder buildHardDisk(String hardDisk){
this.hardDisk = hardDisk;
return this;
}
public ComputerBuilder buildDisplayCard(String displayCard){
this.displayCard = displayCard;
return this;
}
public ComputerBuilder buildPower(String power){
this.power = power;
return this;
}
public ComputerBuilder buildMemory(String memory){
this.memory = memory;
return this;
}
public Computer build(){
return new Computer(this);
}
}
}
②创建测试类
public class Test {
public static void main(String[] args) {
Computer computer = new Computer.ComputerBuilder().buildCPU("酷睿I7").buildMainBoard("华硕主板").build();
System.out.println(computer);
Set<String> set = ImmutableSet.<String>builder().add("a").add("b").build();
System.out.println(set);
}
}
③UML类图
8️⃣建造者模式的实际应用
①在JDK中的应用StringBuilder与StringBuffer,这里仅列举出StringBuilder的append方法,StringBuffer与StringBuilder的区别在于StringBuffer的append方法是同步方法;
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
/**
* Appends the specified {@code StringBuffer} to this sequence.
* <p>
* The characters of the {@code StringBuffer} argument are appended,
* in order, to this sequence, increasing the
* length of this sequence by the length of the argument.
* If {@code sb} is {@code null}, then the four characters
* {@code "null"} are appended to this sequence.
* <p>
* Let <i>n</i> be the length of this character sequence just prior to
* execution of the {@code append} method. Then the character at index
* <i>k</i> in the new character sequence is equal to the character at
* index <i>k</i> in the old character sequence, if <i>k</i> is less than
* <i>n</i>; otherwise, it is equal to the character at index <i>k-n</i>
* in the argument {@code sb}.
*
* @param sb the {@code StringBuffer} to append.
* @return a reference to this object.
*/
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;
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuilder append(char[] str, int offset, int len) {
super.append(str, offset, len);
return this;
}
@Override
public StringBuilder append(boolean b) {
super.append(b);
return this;
}
②建造者模式在Spring中的应用
package org.springframework.beans.factory.support;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.util.ObjectUtils;
public class BeanDefinitionBuilder {
private AbstractBeanDefinition beanDefinition;
private int constructorArgIndex;
public static BeanDefinitionBuilder genericBeanDefinition() {
BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
builder.beanDefinition = new GenericBeanDefinition();
return builder;
}
public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) {
BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
builder.beanDefinition = new GenericBeanDefinition();
builder.beanDefinition.setBeanClass(beanClass);
return builder;
}
public static BeanDefinitionBuilder genericBeanDefinition(String beanClassName) {
BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
builder.beanDefinition = new GenericBeanDefinition();
builder.beanDefinition.setBeanClassName(beanClassName);
return builder;
}
public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass) {
return rootBeanDefinition((Class)beanClass, (String)null);
}
public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass, String factoryMethodName) {
BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
builder.beanDefinition = new RootBeanDefinition();
builder.beanDefinition.setBeanClass(beanClass);
builder.beanDefinition.setFactoryMethodName(factoryMethodName);
return builder;
}
public static BeanDefinitionBuilder rootBeanDefinition(String beanClassName) {
return rootBeanDefinition((String)beanClassName, (String)null);
}
public static BeanDefinitionBuilder rootBeanDefinition(String beanClassName, String factoryMethodName) {
BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
builder.beanDefinition = new RootBeanDefinition();
builder.beanDefinition.setBeanClassName(beanClassName);
builder.beanDefinition.setFactoryMethodName(factoryMethodName);
return builder;
}
public static BeanDefinitionBuilder childBeanDefinition(String parentName) {
BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
builder.beanDefinition = new ChildBeanDefinition(parentName);
return builder;
}
private BeanDefinitionBuilder() {
}
public AbstractBeanDefinition getRawBeanDefinition() {
return this.beanDefinition;
}
public AbstractBeanDefinition getBeanDefinition() {
this.beanDefinition.validate();
return this.beanDefinition;
}
public BeanDefinitionBuilder setParentName(String parentName) {
this.beanDefinition.setParentName(parentName);
return this;
}
public BeanDefinitionBuilder setFactoryMethod(String factoryMethod) {
this.beanDefinition.setFactoryMethodName(factoryMethod);
return this;
}
/** @deprecated */
@Deprecated
public BeanDefinitionBuilder addConstructorArg(Object value) {
return this.addConstructorArgValue(value);
}
public BeanDefinitionBuilder addConstructorArgValue(Object value) {
this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(this.constructorArgIndex++, value);
return this;
}
public BeanDefinitionBuilder addConstructorArgReference(String beanName) {
this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(this.constructorArgIndex++, new RuntimeBeanReference(beanName));
return this;
}
public BeanDefinitionBuilder addPropertyValue(String name, Object value) {
this.beanDefinition.getPropertyValues().add(name, value);
return this;
}
public BeanDefinitionBuilder addPropertyReference(String name, String beanName) {
this.beanDefinition.getPropertyValues().add(name, new RuntimeBeanReference(beanName));
return this;
}
public BeanDefinitionBuilder setInitMethodName(String methodName) {
this.beanDefinition.setInitMethodName(methodName);
return this;
}
public BeanDefinitionBuilder setDestroyMethodName(String methodName) {
this.beanDefinition.setDestroyMethodName(methodName);
return this;
}
public BeanDefinitionBuilder setScope(String scope) {
this.beanDefinition.setScope(scope);
return this;
}
public BeanDefinitionBuilder setAbstract(boolean flag) {
this.beanDefinition.setAbstract(flag);
return this;
}
public BeanDefinitionBuilder setLazyInit(boolean lazy) {
this.beanDefinition.setLazyInit(lazy);
return this;
}
public BeanDefinitionBuilder setAutowireMode(int autowireMode) {
this.beanDefinition.setAutowireMode(autowireMode);
return this;
}
public BeanDefinitionBuilder setDependencyCheck(int dependencyCheck) {
this.beanDefinition.setDependencyCheck(dependencyCheck);
return this;
}
public BeanDefinitionBuilder addDependsOn(String beanName) {
if(this.beanDefinition.getDependsOn() == null) {
this.beanDefinition.setDependsOn(new String[]{beanName});
} else {
String[] added = (String[])ObjectUtils.addObjectToArray(this.beanDefinition.getDependsOn(), beanName);
this.beanDefinition.setDependsOn(added);
}
return this;
}
public BeanDefinitionBuilder setRole(int role) {
this.beanDefinition.setRole(role);
return this;
}
}