1.建造者模式介绍:
属于创建型模式,它提供创建复杂对象的最佳方法,即在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建复杂对象,把内部的建造过程和细节隐藏起来。
1.1优点:
产品的建造和表示分离,实现了解耦。使用建造者模式使客户不必知道产品内部的细节组成,就可以获取到相应的对象。使得创建的过程更加的清晰,具体的建造类直接是独立的,这有利于系统的扩展。增加新的具体建造者无需修改原有类库的代码,符合“开闭原则”。
1.2缺点:
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。系统相对来说比较庞大。
1.3例子:
比如:
工厂(建造者模式:):负责制造汽车(组装过程和细节咋工厂内)。
汽车购买者(用户):你只需要说出你需要的啥型号,然后直接购买就可以使用了,无需知道汽车是怎么生产的组装的(发动机,方向盘,轮子等等)。
即通过工厂模式生产零件----使用建造者模式去组装工厂生产出来的零件使用
2.例子一:
造房子例子:假设造房子步骤为:打地基—砌墙—水电安装--粉刷。如果要盖一个房子,首先需要找一个建筑公司包工头(指挥者),指挥工人(具体建造者)过来造房子(产品),最后验收。
我们可以通过这个步骤建造高楼,也可以建造平房。这就是同一过程生产不同的表示。
产品类----房子:
package builder.demo;
//具体的房子
public class Product {
private String buildA;
private String buildB;
private String buildC;
private 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 + "]";
}
}
抽象的建造者接口,定义了一个创建对象的公共规则:
package builder.demo;
//抽象的建造者,只是定义一些建房子的规则,并不实际去建房子。
public abstract class Builder {
//A,B,C,D表示建房子的四个步骤
abstract void buildA(); //地基
abstract void buildB();//砌墙
abstract void buildC();//水电
abstract void buildD();//粉刷
//得到具体的房子,即完工了
abstract Product getProduct();
}
继承这个抽象接口的建造者子类,在这个例子中则是工人Worker,工人直接负责创建实际的产品
package builder.demo;
//具体建造者
public class Worker extends Builder {
private Product product;
//这里的构造方法直接new一个产品进去
public Worker() {
product = new Product();
}
@Override
void buildA() {
// TODO Auto-generated method stub
product.setBuildA("地基");
System.out.println("地基");
}
@Override
void buildB() {
// TODO Auto-generated method stub
product.setBuildB("砌墙");
System.out.println("砌墙");
}
@Override
void buildC() {
// TODO Auto-generated method stub
product.setBuildC("水电");
System.out.println("水电");
}
@Override
void buildD() {
// TODO Auto-generated method stub
product.setBuildD("粉刷");
System.out.println("粉刷");
}
@Override
Product getProduct() {
// TODO Auto-generated method stub
return product;
}
}
指挥者类:相当于例子中的包工头,将创建对象的过程交给指挥者来实现,对象如果构建,由指挥者决定:
package builder.demo;
//指挥:核心。负责指挥构建一个工程,工程如何构建,由它决定。
public class Director {
//指挥工人按照顺序建造房子,即设计产品的参数。ABCD。
public Product build(Builder builder) {//父类对象变量可以直接引用子类对象
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
return builder.getProduct();
}
}
Test:
package builder.demo;
/**
* 第一种建造者模式
* 本示例是指挥者模式最常规的用法,指挥类Directory指挥Worker。指挥者在Builder中很重要
* 它用于指导具体的构建者如何构建产品,控制调用的先后顺序等等,并向调用者返回完整的产品类,有时间可以
* 把指挥者和抽象建造者进行结合。
* @author Clay
*
*/
public class Test {
public static void main(String args[]) {
//指挥
Director director = new Director();
//指挥具体的工人完成产品
Product product = director.build(new Worker());
System.out.println(product.toString());
}
}
3.例子二:
麦当劳的套餐,服务员(具体的建造者。)可以随意搭配几种产品(零件)组成一款套餐(产品),然后出售给客户。比第一种方式少了指挥者,主要是因为第二种方式把指挥者交给用户来操作,使得产品的创建更加简单灵活。
产品类,这里的产品类的属性赋予了初始值,即不通过指挥类指挥构建对象也可以直接通过Worker类获取一个默认的对象,这里是例子里面的套餐。
package builder.demo02;
//产品。实际需要的对象
public class Product {
private String buildA = "汉堡";
private String buildB = "饮料";
private String buildC = "水果";
private 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 + "]";
}
}
抽象的建造者:
package builder.demo02;
//抽象的建造者
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();
}
建造者类:
package builder.demo02;
public class Test {
public static void main(String[] args) {
//服务员
Worker worker = new Worker();
//点餐。链式编程
//在原来的基础上可以自由组合了,不组合也可以用原有的套餐
Product product = worker.buildA("全家桶").
buildB("雪碧").getProduct();
//用餐
System.out.println(product.toString());
}
}
package builder.demo02;
public class Worker extends Builder {
private Product product;
public Worker() {
// TODO Auto-generated constructor stub
product = new Product();
}
@Override
Builder buildA(String msg) {
// TODO Auto-generated method stub
product.setBuildA(msg);
return this;
}
@Override
Builder buildB(String msg) {
// TODO Auto-generated method stub
product.setBuildB(msg);
return this;
}
@Override
Builder buildC(String msg) {
// TODO Auto-generated method stub
product.setBuildC(msg);
return this;
}
@Override
Builder buildD(String msg) {
// TODO Auto-generated method stub
product.setBuildD(msg);
return this;
}
@Override
Product getProduct() {
// TODO Auto-generated method stub
return product;
}
}
4.总结:
建造者模式,就是通过一个建造者类,一个一个的给对象的属性赋值,其中例子二中的方法更加灵活,可以让用户自己去构建自己想要的对象。
应用场景:需要生产的产品对象有复杂的内部结构,这些产品有相同的共性。适合具有较多的属性的对象创建过程。
建造者和抽象工厂模式的比较:建造者模式返回一个组装好的产品,而抽象工厂返回一系列的相关的产品(这些产品位于不同的产品等级,构成一个产品族)。如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。