建造者模式
建造者模式属于创建型模式,它提供了一种创建对象的最佳方式。
定义:
- 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
主要作用:
- 在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
- 用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建纷杂对象(把内部的建造过程和细节隐藏起来)。
例子:
- 工厂(建造者模式):负责制造汽车(组装过程和细节在工厂内)。
- 汽车购买者(用户):只需要说出需要的型号或对象的内容即可直接购买。
举例:
//抽象的建造者:方法
public abstract class Builder {
abstract void buildA();
abstract void buildB();
abstract void buildC();
abstract void buildD();
//得到产品
abstract Product getProduct();
}
//产品
public class Product {
private String buidA;
private String buidB;
private String buidC;
private String buidD;
public String getBuidA() {
return buidA;
}
public void setBuidA(String buidA) {
this.buidA = buidA;
}
public String getBuidB() {
return buidB;
}
public void setBuidB(String buidB) {
this.buidB = buidB;
}
public String getBuidC() {
return buidC;
}
public void setBuidC(String buidC) {
this.buidC = buidC;
}
public String getBuidD() {
return buidD;
}
public void setBuidD(String buidD) {
this.buidD = buidD;
}
}
//具体建造者
public class Worker extends Builder {
private Product product;
public Worker(){
product = new Product();
}
@Override
void buildA() {
product.setBuidA("工程A");
System.out.println("工程A");
}
@Override
void buildB() {
product.setBuidA("工程B");
System.out.println("工程B");
}
@Override
void buildC() {
product.setBuidA("工程C");
System.out.println("工程C");
}
@Override
void buildD() {
product.setBuidA("工程D");
System.out.println("工程D");
}
@Override
Product getProduct() {
return product;
}
}
//指挥:核心。负责指挥构建工程
public class Director {
//指挥建造
public Product build(Builder builder){
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
return builder.getProduct();
}
}
//测试
public class Test {
public static void main(String[] args){
Director director = new Director();
Product build = director.build(new Worker());
}
}
//打印:
工程A
工程B
工程C
工程D
Process finished with exit code 0
- 上面的示例是建造者模式的常规用法,导演类Director在Builder模式中具有很重要的作用,它用于指导具体构建这如何让构建产品,控制调用先后顺序,并向调用者返回完整的产品类,但是有些情况下需要简化系统结构,可以把Director和抽象建造者进行结合。
- 通过静态内部类方式实现零件无序装配构造,这种方式使用更加灵活,更符合定义。内部有复杂对象的默认实现,使用时可以根据需求自由定义更改内容,并且无需改变具体的构造方式,就可以生产出不同的复杂产品。
举例:
//建造者
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 {
private String BuildA = "工程A";
private String BuildB = "工程B";
private String BuildC = "工程C";
private String BuildD = "工程D";
public String getBuildA() {
return BuildA;
}
public void setBuildA(String buildA) {
BuildA = buildA;
}
public String getBuildB() {
return BuildB;
}
public void setBuildB(String buildB) {
BuildB = buildB;
}
public String getBuildC() {
return BuildC;
}
public void setBuildC(String buildC) {
BuildC = 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();
}
@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 product = worker
.buildA("A->A")
.buildB("B->B")
.buildC("C->C")
.buildD("D->D")
.getProduct();
System.out.println(product.toString());
}
}
//打印:
Product{BuildA'A->A'BuildB'B->B'BuildC'C->C'BuildD'D->D'}
Process finished with exit code 0
优点:
- 产品的建造和表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节。
- 将复杂的产品的创建步骤分解在不同的方法中,是的创建过程更加清晰。
- 具体的建造者类之间相互独立的,这有利于系统的扩展。增减新的具体建造者无需修改原有类库的代码,符合“开闭原则”。
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间差异性很大,则不适合使用建造者模式,因此其使用范围收到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
应用场景:
- 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
- 适合于一个具有较多零件(属性)的产品(对象)的创建过程。
建造者与抽象工厂模式比较:
- 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来知道如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
- 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。