设计模式之建造者模式
1、什么是建造者模式(Builder)
建造者模式: 指将一个复杂的对象的的构造与它的表示分离,使得同样的建造过程可以创建不同的形式
建造者模式图解:
2、建造者一般有以下几种角色:
1、抽象建造者(Builder):抽象要建造的东西的结构,规范产品对象各个部分的组成。这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的对象部件的创建。
2、产品类(Product):要创建的复杂对象。
3、产品建造者(Worker):实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。在构造过程完成后,提供产品的实例。
4、指挥者(Leader):调用具体的建造者来建造复杂对象的各个部分。在指导者中不涉及主要的产品的信息。只负责保证对象各部分完整创建或按某种顺序创建。
3、简单例子
比如建造一座房子:
1、抽象建造者
//抽象建造者
public abstract class Builder {
//定义抽象方法 建造的抽象方法
abstract void BuildA(); //铺地基
abstract void BuildB(); //水泥工程
abstract void BuildC(); //铺电线
abstract void BuildD(); //粉刷
//会得出产品
abstract Product getProduct();
}
2、产品类:
//产品: 房子
public class Product {
public String buildA; //蒲地基
public String buildB;//水泥工程
public String buildC;//铺电线
public String buildD;//粉刷
//得到产品所需要的步骤
public String getBuildA() {
return buildA;
}
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public String getBuildC() {
return buildC;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
public String getBuildD() {
return buildD;
}
public void setBuildD(String buildD) {
this.buildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' +
'}';
}
}
3、产品建造者:
//具体的建造者 : 工人
public class Worker extends Builder{
Product product;
public Worker() {
product = new Product();//工人建造的产品
}
@Override
void BuildA() {
product.setBuildA("地基");
System.out.println("地基");
}
@Override
void BuildB() {
product.setBuildB("水泥工程");
System.out.println("水泥工程");
}
@Override
void BuildC() {
product.setBuildC("铺电线");
System.out.println("铺电线");
}
@Override
void BuildD() {
product.setBuildD("粉刷");
System.out.println("粉刷");
}
@Override
Product getProduct() {
return product;
}
}
4、指挥者:
//需要一个指挥者来负责指挥建造房子 指挥: 核心 产品如何构造由他决定
public class Leader {
//指挥构建产品的顺序 指挥工人 builder worker继承builder
public Product build(Builder builder){
builder.BuildA();
builder.BuildB();
builder.BuildC();
builder.BuildD();
return builder.getProduct();
}
}
还可以在抽象建造者中使用静态内部类,可以不用指挥者,选择权利交到产品建造者手中:
例如 服务员配置套餐, 套餐有默认套餐,但是服务员可以根据顾客需求更换不同的产品组成部分构成不同的套餐。
//抽象建造者
public abstract class Builder {
//静态内部类
abstract Builder buildA(String msg);
abstract Builder buildB(String msg);
abstract Builder buildC(String msg);
abstract Builder buildD(String msg);
abstract Product getProduct();//得到一份套餐
}
产品:
//产品 : 套餐
public class Product {
//默认套餐
public String BuildA = "汉堡";
public String BuildB = "可乐";
public String BuildC = "鸡翅";
public String BuildD = "薯条";
public void setBuildA(String buildA) {
BuildA = buildA;
}
public void setBuildB(String buildB) {
BuildB = buildB;
}
public void setBuildC(String buildC) {
BuildC = buildC;
}
public String getBuildA() {
return BuildA;
}
public String getBuildB() {
return BuildB;
}
public String getBuildC() {
return BuildC;
}
public String getBuildD() {
return BuildD;
}
public void setBuildD(String buildD) {
BuildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"BuildA='" + BuildA + '\'' +
", BuildB='" + BuildB + '\'' +
", BuildC='" + BuildC + '\'' +
", BuildD='" + BuildD + '\'' +
'}';
}
}
产品建造者
//服务员
public class Worker extends Builder{
private Product product;
public Worker(){
product = new Product();
}
//服务员 可以根据顾客选择设计套餐的内容 msg就是顾客选择
@Override
Builder buildA(String msg) {
product.setBuildA(msg);
return this;
}
@Override
Builder buildB(String msg) {
product.setBuildB(msg);
return this;
}
@Override
Builder buildC(String msg) {
product.setBuildC(msg);
return this;
}
@Override
Builder buildD(String msg) {
product.setBuildD(msg);
return this;
}
@Override
Product getProduct() {
return product;
}
}
测试类:可以更换不同的产品组件得到不同的套餐
public class Test {
public static void main(String[] args) {
Worker worker = new Worker();
Product product1 = worker.getProduct();//获得默认套餐
System.out.println("默认套餐");
System.out.println(product1.toString());
//自定义
System.out.println("自定义套餐");
Product product2 = worker.buildA("全家桶").buildB("雪碧").getProduct();
System.out.println(product2.toString());
}
}
4、适用场景
- 需要生产的生产对象有复杂的产品结构
- 需要生产的产品对象的属性互相依赖,建造者可以强迫生成顺序
- 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
5、优点
- 使用建造者模式可以让客户端不需要知道产品内部的必要细节(买东西不需要明白产品是怎么生产的)(封装性)
- 具体的建造者之间是相互独立的,对系统扩展非常有利
- 由于具体的构造者是独立的,所以可以对建造过程逐步细化,而不对其他模块产生影响
6、与工厂模式的区别
在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,指导者联系建造者最后得到产品。即建造模式可以强制实行一种分步骤进行的构造过程。工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类想客户端提供最终的产品。而在建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给指导者,由指导者负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
7、JDK中的建造者模式:
- java.lang.StringBuilder#append()
- java.lang.StringBuffer#append()
- java.sql.PreparedStatement