将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
顾名思义,建造者模式是用于构建对象的,但是与常规构造不同的是,它是通过构建复杂的流程去构建一个新的对象。比如盖房子,需要打地基,搭钢筋,铺电路,粉刷墙壁等流程。再比如生产手机,会有安装屏幕,安装CPU,安装电池等步骤。这些东西的构建都有固定的流程与执行方法,只是根据业务需求的不同,执行周期和用量的也会有所不同,此时就可以使用建造者模式。
建造者模式将固定的逻辑抽象,根据不同的需求进行不同是实体类实现,然后通过指挥类进行具体的流程操控,对客户进行封闭,客户只需要选择最终希望的构建模式即可。
两者同样是抽象具体的工作,使用户可以不用关心具体细节而直接进行调用。但是,两种模式不同之处在于,建造者模式是处理如何建造实例对象问题,其侧重点在于通过构建流程创建新的对象;而工厂模式是处理如何获取实例对象问题,侧重点在于封装对象的创建。
如何使用建造者模式写代码呢?我们以盖房子为例:无论是普通房子还是单元楼,都需要打地基,搭钢筋,走电路,粉刷墙等步骤,那么这些东西就可以抽象成一个通用类
//抽象类
public abstract class Builder {
public abstract void buildA();
public abstract void buildB();
public abstract void buildC();
public abstract void buildD();
public abstract Product getProoduct();
}
随后,应该有需要构建的具体对象
//实例对象,即构建的房间对象
public class Product {
private String buildA;
private String buildB;
private String buildC;
private String buildD;
//set();
//toString();
对象如何构建呢?那么就需要工人来决定到底功能有哪些,并进行对象的实例化
public class Worker extends Builder{
//对象属性
private Product product;
//构造方法中进行对象的创建
public Worker() {
product = new Product();
}
@Override
public void buildA() {
product.setBuildA("地基");
System.out.println("打地基");
}
@Override
public void buildB() {
product.setBuildB("钢筋");
System.out.println("钢筋工程");
}
@Override
public void buildC() {
product.setBuildC("铺电线");
System.out.println("铺电线");
}
@Override
public void buildD() {
product.setBuildD("墙面");
System.out.println("粉刷墙面");
}
//外部获得对象的方法
@Override
public Product getProduct() {
return product;
}
}
最重要的一点,我们需要一个总指挥(Director)来进行安排操作,Worker只是Builder的具体实现类,不同的房屋类型可以有不同的Worker,然后由Director进行先后次序的控制,并向调用者返回完整的类。
public class Director {
//进行具体流程的顺序安排
public Product build(Builder builder) {
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
//随后,让Builder构建对象
return builder.getProduct();
}
}
以上,整个房子构建就可以完成了,我们来进行一下测试:
public static void main(String[] args) {
Director director = new Director();
director.build(new Worker());
}
以上代码是建造者模式的常规用法,但是有些情况下需要简化系统结构,将抽象构建者与Director进行结合。我们可以使用静态内部类的方式实现无序装配构造,内部有默认实现的同时,还可以让用户自定义内容,无需改变具体的构造方式就可以生产出不同的复杂产品,典型的例子就有套餐的搭配。我们去KFC吃东西可以有默认的套餐,也可以用户自定义吃食,我们让用户自己成为Director,使得产品的创建更加灵活。
首先,创建产品,并有默认值,即为默认套餐
//套餐
public class Product {
//赋值,为默认套餐
private String buildA = "汉堡";
private String buildB = "薯条";
private String buildC = "可乐";
//set()
//toString()
}
抽象构建者
//建造者
public abstract class Builder {
//可以让用户自己赋值,如果不赋值,则为默认套餐
abstract public Builder buildA(String str);
abstract public Builder buildB(String str);
abstract public Builder buildC(String str);
abstract public Product getProduct();
}
服务员类,是建造者的实现类
//服务员类,实现让用户自己点餐的细节
public class Worker extends Builder {
private Product product;
public Worker() {
product = new Product();
}
@Override
public Builder buildA(String str) {
product.setBuildA(str);
return this;
}
@Override
public Builder buildB(String str) {
product.setBuildB(str);
return this;
}
@Override
public Builder buildC(String str) {
product.setBuildC(str);
return this;
}
@Override
public Product getProduct() {
return product;
}
}
测试:
public class Main {
public static void main(String[] args) {
//得到默认套餐
Product product = new Worker().getProduct();
System.out.println(product);
//进行自定义选择
product.setBuildA("炸鸡");
System.out.println(product);
}
}