- 定义
将复杂的对象创建过程抽象出来,抽象过程的不同构建出来的产品对象也不一样,允许用户指定要创建的对象类型,但是不需要知道具体的构建过程。
- 结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tgk2rAUQ-1577697105841)(https://user-images.githubusercontent.com/35365788/71477175-87785c80-2823-11ea-8e47-e0191cda88ba.png)]
-
优点
- 产品和产品之间的创建过程解耦,客户端不需要了解创建的具体细节,相同创建过程创建不同的产品对象
- 产品的创建过程可控,创建逻辑清晰
- 具体的建造者之间的解耦,具体的建造者之间独立,对新增和修改开放,无需修改原有的类库
- 指挥者针对抽象编程,拓展方便,符合’开闭原则‘
-
缺点
- 需要建造的过程有共同的相似点,差异大不适合
- 建造过程不能过于复杂,否则会创建很多的具体的创建者
-
建造者模式与抽象工厂模式的比较:
-
与抽象工厂模式相比
建造者模式返回一个组装好的完整产品 ,而 抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
如果将抽象工厂模式看成 汽车配件生产工厂 ,生产一个产品族的产品,那么建造者模式就是一个 汽车组装工厂 ,通过对部件的组装可以返回一辆完整的汽车。
举例一个简单的demo
产品
package com.example.design.pattern.book.builder;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Product {
private String partA;
private String partB;
private String partC;
}
package com.example.design.pattern.book.builder;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Product {
private String partA;
private String partB;
private String partC;
}
抽象建造者
public abstract class Builder {
Product product = new Product();
abstract void buildPertA();
abstract void buildPertB();
abstract void buildPertC();
public Product getProduct() {
return product;
}
}
具体建造者A
public class BuilderA extends Builder {
@Override
void buildPertA() {
product.setPartA("AAAA");
}
@Override
void buildPertB() {
product.setPartB("AAAA");
}
@Override
void buildPertC() {
product.setPartC("AAAA");
}
}
具体建造者B
public class BuilderB extends Builder {
@Override
void buildPertA() {
product.setPartA("BBBB");
}
@Override
void buildPertB() {
product.setPartB("BBBB");
}
@Override
void buildPertC() {
product.setPartC("BBBB");
}
}
指导者
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product build(){
builder.buildPertA();
builder.buildPertB();
builder.buildPertC();
return builder.getProduct();
}
}
测试用例
@Test
public void testBuilder(){
BuilderA builderA = new BuilderA();
Director director = new Director(builderA);
Product product = director.build();
System.out.println(product);
}
举例一个简单的肯德基建造例子
参考文章
https://blog.csdn.net/qq_34337272/article/details/80540059
套餐产品(主食和饮料)
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Meal {
private String food;
private String drink;
}
套餐抽象建造者(抽象建造者)
public abstract class MealBuilder {
Meal p = new Meal();
abstract void buildFood();
abstract void buildDrink();
public Meal getProduct() {
return p;
}
}
套餐A(具体的建造者)
public class MealA extends MealBuilder {
@Override
void buildFood() {
p.setFood("汉堡");
}
@Override
void buildDrink() {
p.setDrink("可乐");
}
}
套餐B(具体建造者)
public class MealB extends MealBuilder {
@Override
void buildFood() {
p.setFood("鸡腿");
}
@Override
void buildDrink() {
p.setDrink("雪碧");
}
}
服务员(指导者)
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Waiter {
private MealBuilder mealBuilder;
public Meal construct(){
mealBuilder.buildDrink();
mealBuilder.buildFood();
return mealBuilder.getProduct();
}
}
测试用例
@Test
public void testMeal() {
//套餐A
MealA mealA = new MealA();
//服务员A
Waiter director1 = new Waiter(mealA);
//由套餐A组成的产品
Meal product = director1.construct();
System.out.println("套餐A的内容:" + product);
//套餐B
MealB mealB = new MealB();
//服务员B
Waiter director2 = new Waiter(mealB);
//由套餐B组成的产品
Meal product1 = director2.construct();
System.out.println("套餐B的内容:" + product1);
}