23种设计模式之建造者模式
建造者模式
-
建造者模式也属于创建型模式,它提供了一种创建对象的最佳方式。
-
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
-
主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建负责的对象。
-
用户只需要给出指定复杂的类型和内容,建造者模式负责按顺序创建复杂对象(把内部的创建过程和细节隐藏起来)
-
例子:
工厂(建造者模式):负责制造汽车(组装过程和细节在工厂内)
汽车购买者(用户):你只需要说出你需要的型号(对象的类型和内容),然后直接购买就可以使用(不需要指定汽车是怎么组装的(车轮、车门、发动机等等))
角色分析:
比如:建筑公司或者工程承包商(指挥者),承包商指挥工人(具体建造者)造房子。
抽象建造者代码:
package builder;
/**
* @Description
* @Author wangkui
* @Date 2022-08-24 18:42
* @Version 1.0
*/
public abstract class Builder {
/**
* 地基
*/
abstract void buildA();
/**
* 钢筋
*/
abstract void buildB();
/**
* 电线
*/
abstract void buildC();
/**
* 粉刷
*/
abstract void buildD();
/**
* 得到产品
* @return 产品
*/
abstract Product getProduct();
}
具体产品:
package builder;
/**
* @Description
* @Author wangkui
* @Date 2022-08-24 18:44
* @Version 1.0
*/
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;
/**
* @Description
* @Author wangkui
* @Date 2022-08-24 18:46
* @Version 1.0
*/
public class Worker extends Builder{
/**
* 产品
*/
private final 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("粉刷");
}
/**
* 得到产品
*
* @return 产品
*/
@Override
Product getProduct() {
return product;
}
}
指挥者:
package builder;
/**
* @Description 指挥:核心 负责指挥构建一个工程,工程如何构建由它决定
* @Author wangkui
* @Date 2022-08-24 18:51
* @Version 1.0
*/
public class Director {
public Product build(Builder builder) {
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
return builder.getProduct();
}
}
测试:
package builder;
/**
* @Description
* @Author wangkui
* @Date 2022-08-24 18:53
* @Version 1.0
*/
public class Test {
public static void main(String[] args) {
Director director = new Director();
Product build = director.build(new Worker());
System.out.println(build.toString());
}
}
- 上面示例是Builder模式的常规用法,导演类Director在Builder模式中具有很重要的作用,它用于指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类,但是有些情况下需要简化系统结构,可以把Director和抽象建造者进行结合。
- 通过静态内部类方式实现零件无序装配构造,这种方式使用更加灵活,更符合定义。内部有复杂对象的默认实现,使用时可以根据用户需求自由定义更改内容,并且无需改变具体的构造方式。就可以生产出不同复杂产品
- 比如麦当劳的套餐,服务员(具体建造者)可以随意搭配任意几种产品(零件)组成一款套餐(产品),然后出售给客户。比第一种方式少了指挥者,主要是因为第二种方式把指挥者交给用户来操作,使得产品的创建更加简单灵活。
抽象建造者:
package builder.demo02;
/**
* @Description
* @Author wangkui
* @Date 2022-08-24 18:42
* @Version 1.0
*/
public abstract class Builder {
/**
* 汉堡
* @param msg msg
* @return Builder
*/
abstract Builder buildA(String msg);
/**
* 可乐
* @param msg msg
* @return Builder
*/
abstract Builder buildB(String msg);
/**
* 饮料
* @param msg msg
* @return Builder
*/
abstract Builder buildC(String msg);
/**
* 甜点
* @param msg msg
* @return Builder
*/
abstract Builder buildD(String msg);
/**
* 得到产品
* @return 产品
*/
abstract Product getProduct();
}
产品:
package builder.demo02;
/**
* @Description
* @Author wangkui
* @Date 2022-08-24 18:44
* @Version 1.0
*/
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;
/**
* @Description
* @Author wangkui
* @Date 2022-08-24 19:14
* @Version 1.0
*/
public class Worker extends Builder{
private final Product product;
public Worker() {
product = new Product();
}
/**
* 汉堡
*
* @param msg msg
* @return Builder
*/
@Override
Builder buildA(String msg) {
product.setBuildA(msg);
return this;
}
/**
* 可乐
*
* @param msg msg
* @return Builder
*/
@Override
Builder buildB(String msg) {
product.setBuildB(msg);
return this;
}
/**
* 饮料
*
* @param msg msg
* @return Builder
*/
@Override
Builder buildC(String msg) {
product.setBuildC(msg);
return this;
}
/**
* 甜点
*
* @param msg msg
* @return Builder
*/
@Override
Builder buildD(String msg) {
product.setBuildD(msg);
return this;
}
/**
* 得到产品
*
* @return 产品
*/
@Override
Product getProduct() {
return product;
}
}
测试:
package builder.demo02;
/**
* @Description
* @Author wangkui
* @Date 2022-08-24 19:16
* @Version 1.0
*/
public class Test {
public static void main(String[] args) {
Worker worker = new Worker();
Product product = worker.buildA("鸡腿").getProduct();
System.out.println(product.toString());
}
}
优点:
产品的建造和表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
具体的建造者类之间是相互独立的,这有利于系统的扩展。增加新的具体建造者无需修改原有类库的代码,符合“开闭原则“。
缺点:
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
应用场景:
需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;
隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
适合于一个具有较多的零件(属性)的产品(对象)的创建过程。
建造者与抽象工厂模式的比较:
与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车!