概述
Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种。Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
如何解决:将变与不变分离开。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
应用实例: 1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。 2、JAVA 中的 StringBuilder。
优点: 1、建造者独立,易扩展。 2、便于控制细节风险。
缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。
使用场景: 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
举个例子理解
我们要生产一个Hamburger,假设需要黄油、芥末、番茄酱、沙拉酱、洋葱、黄瓜这些原材料。下面模拟这个生产过程
//Hamburger类
package com.xnn;
/**
* 类(接口)描述:
* @author xnn
* 2018年11月1日下午6:19:51
*/
public class Hamburger {
//黄油
private String grease;
//芥末
private String mustard;
//番茄酱
private String redeye;
//沙拉酱
private String mayonnaise;
//洋葱
private String onion;
//黄瓜
private String cucumber;
/**
* @return the grease
*/
public String getGrease() {
return grease;
}
/**
* @param grease the grease to set
*/
public void setGrease(String grease) {
this.grease = grease;
}
/**
* @return the mustard
*/
public String getMustard() {
return mustard;
}
/**
* @param mustard the mustard to set
*/
public void setMustard(String mustard) {
this.mustard = mustard;
}
/**
* @return the redeye
*/
public String getRedeye() {
return redeye;
}
/**
* @param redeye the redeye to set
*/
public void setRedeye(String redeye) {
this.redeye = redeye;
}
/**
* @return the mayonnaise
*/
public String getMayonnaise() {
return mayonnaise;
}
/**
* @param mayonnaise the mayonnaise to set
*/
public void setMayonnaise(String mayonnaise) {
this.mayonnaise = mayonnaise;
}
/**
* @return the onion
*/
public String getOnion() {
return onion;
}
/**
* @param onion the onion to set
*/
public void setOnion(String onion) {
this.onion = onion;
}
/**
* @return the cucumber
*/
public String getCucumber() {
return cucumber;
}
/**
* @param cucumber the cucumber to set
*/
public void setCucumber(String cucumber) {
this.cucumber = cucumber;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Hamburger [grease=" + grease + ", mustard=" + mustard
+ ", redeye=" + redeye + ", mayonnaise=" + mayonnaise
+ ", onion=" + onion + ", cucumber=" + cucumber + "]";
}
}
//客户端
package com.xnn;
/**
* 类(接口)描述:
* @author xnn
* 2018年11月1日下午6:15:52
*/
public class MainClass {
public static void main(String[] args) {
Hamburger hamburger = new Hamburger();
hamburger.setCucumber("一根黄瓜");
hamburger.setGrease("一两黄油");
/**
* .............................这样造对象甚是麻烦,如果属性再多一点,代码量更大,就算提供全参构造器,那也会造成参数很长
*/
//这样写,客户端代码省去了很多
/*BuilderHamburgerImpl builderHamburgerImpl = new BuilderHamburgerImpl();
BuilderHamburgerImpl1 builderHamburgerImpl1 = new BuilderHamburgerImpl1();
Directer directer = new Directer();
Hamburger createHamburger = directer.CreateHamburger(builderHamburgerImpl);
System.out.println(createHamburger);
Hamburger createHamburger2 = directer.CreateHamburger(builderHamburgerImpl1);
System.out.println(createHamburger2);*/
}
}
下面用建造者模式去写
Hanburger类
package com.xnn;
/**
* 类(接口)描述:
* @author xnn
* 2018年11月1日下午6:19:51
*/
public class Hamburger {
//黄油
private String grease;
//芥末
private String mustard;
//番茄酱
private String redeye;
//沙拉酱
private String mayonnaise;
//洋葱
private String onion;
//黄瓜
private String cucumber;
/**
* @return the grease
*/
public String getGrease() {
return grease;
}
/**
* @param grease the grease to set
*/
public void setGrease(String grease) {
this.grease = grease;
}
/**
* @return the mustard
*/
public String getMustard() {
return mustard;
}
/**
* @param mustard the mustard to set
*/
public void setMustard(String mustard) {
this.mustard = mustard;
}
/**
* @return the redeye
*/
public String getRedeye() {
return redeye;
}
/**
* @param redeye the redeye to set
*/
public void setRedeye(String redeye) {
this.redeye = redeye;
}
/**
* @return the mayonnaise
*/
public String getMayonnaise() {
return mayonnaise;
}
/**
* @param mayonnaise the mayonnaise to set
*/
public void setMayonnaise(String mayonnaise) {
this.mayonnaise = mayonnaise;
}
/**
* @return the onion
*/
public String getOnion() {
return onion;
}
/**
* @param onion the onion to set
*/
public void setOnion(String onion) {
this.onion = onion;
}
/**
* @return the cucumber
*/
public String getCucumber() {
return cucumber;
}
/**
* @param cucumber the cucumber to set
*/
public void setCucumber(String cucumber) {
this.cucumber = cucumber;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Hamburger [grease=" + grease + ", mustard=" + mustard
+ ", redeye=" + redeye + ", mayonnaise=" + mayonnaise
+ ", onion=" + onion + ", cucumber=" + cucumber + "]";
}
}
package com.xnn;
/**
* 类(接口)描述:创建Hamburger的接口,里面声明了创建Hamburger所需要的各种原料的方法,以及创建一个完整Hamburger的方法
* @author xnn
* 2018年11月1日下午6:49:13
*/
public interface IBuilderHamburger {
//创建黄油
public void builderGrease();
//创建芥末
public void builderMustard();
//创建番茄酱
public void builderRedeye();
//创建沙拉酱
public void mayonnaise();
//创建洋葱
public void builderOnion();
//创建黄瓜
public void builderCucumber();
//创建汉堡包
public Hamburger createHamburger();
}
package com.xnn;
/**
* 类(接口)描述:IBuilderHamburger接口的具体实现类,负责创建具体的Hamburger
* @author xnn
* 2018年11月1日下午6:57:13
*/
public class BuilderHamburgerImpl implements IBuilderHamburger{
private Hamburger hamburger;
//在构造方法中创建出一个hamburger对象
public BuilderHamburgerImpl() {
super();
hamburger = new Hamburger();
}
public void builderGrease() {
hamburger.setGrease("一两黄油的");
}
public void builderMustard() {
hamburger.setMustard("一两芥末的");
}
public void builderRedeye() {
hamburger.setRedeye("一两番茄酱的");
}
public void mayonnaise() {
hamburger.setMayonnaise("一两沙拉酱的");
}
public void builderOnion() {
hamburger.setOnion("一个洋葱的");
}
public void builderCucumber() {
hamburger.setCucumber("一根黄瓜的");
}
public Hamburger createHamburger() {
System.out.println("创造出来了一个原料全是一两的hamburger");
return hamburger;
}
}
package com.xnn;
/**
* 类(接口)描述:IBuilderHamburger接口的另一个具体实现类,负责创建具体的Hamburger
* @author xnn
* 2018年11月1日下午8:07:26
*/
public class BuilderHamburgerImpl1 implements IBuilderHamburger {
private Hamburger hamburger;
//在构造方法中创建出一个hamburger对象
public BuilderHamburgerImpl1() {
super();
hamburger = new Hamburger();
}
public void builderGrease() {
hamburger.setGrease("二两黄油的");
}
public void builderMustard() {
hamburger.setMustard("二两芥末的");
}
public void builderRedeye() {
hamburger.setRedeye("二两番茄酱的");
}
public void mayonnaise() {
hamburger.setMayonnaise("二两沙拉酱的");
}
public void builderOnion() {
hamburger.setOnion("二个洋葱的");
}
public void builderCucumber() {
hamburger.setCucumber("二根黄瓜的");
}
public Hamburger createHamburger() {
System.out.println("创造出来了一个原料全是二两的hamburger");
return hamburger;
}
}
package com.xnn;
/**
* 类(接口)描述:客户端类
* @author xnn
* 2018年11月1日下午6:15:52
*/
public class MainClass {
public static void main(String[] args) {
/*Hamburger hamburger = new Hamburger();
hamburger.setCucumber("一根黄瓜");
hamburger.setGrease("一两黄油");*/
/**
* .............................这样造对象甚是麻烦,如果属性再多一点,代码量更大
*/
//这样写,客户端代码省去了很多,隐藏了很多创建对象的细节。
BuilderHamburgerImpl builderHamburgerImpl = new BuilderHamburgerImpl();
BuilderHamburgerImpl1 builderHamburgerImpl1 = new BuilderHamburgerImpl1();
Directer directer = new Directer();
Hamburger createHamburger = directer.CreateHamburger(builderHamburgerImpl);
System.out.println(createHamburger);
Hamburger createHamburger2 = directer.CreateHamburger(builderHamburgerImpl1);
System.out.println(createHamburger2);
}
}
对应的类图:
运行结果:
创造出来了一个原料全是一两的hamburger
Hamburger [grease=一两黄油的, mustard=一两芥末的, redeye=一两番茄酱的, mayonnaise=null, onion=一个洋葱的, cucumber=一根黄瓜的]
创造出来了一个原料全是二两的hamburger
Hamburger [grease=二两黄油的, mustard=二两芥末的, redeye=二两番茄酱的, mayonnaise=null, onion=二个洋葱的, cucumber=二根黄瓜的]