1. 概念
- 建造者模式(Builder Pattern)又叫生成器模式,是一种创建型设计模式,用于将复杂对象的构建过程与其表示分离,以便相同的构建过程可以创建不同的表示。这种模式特别适用于创建那些具有多个组成部分、步骤复杂或者产品具有多种不同变化的对象。
2. 原理结构图
- 原理结构图说明
- 产品(Product):这是最终要创建的复杂对象,它由多个部件组成,这些部件可能有不同的创建和组装过程。
- 抽象建造者(Builder):这个角色定义了创建产品对象的各个部件所需的抽象接口。通常会声明两类方法,一类是buildXXX()方法,用于创建复杂对象的各个部分;另一类是getResult()方法,用于返回最终的复杂对象。
- 具体建造者(ConcreteBuilder):这个角色实现了抽象建造者的接口或继承了抽象建造者的类。它负责实现各个部件的具体构造和装配方法,并定义所创建的复杂对象。具体建造者还可能提供一个方法来返回创建好的复杂对象。
- 指挥者(Director):这个角色负责按照特定的顺序调用具体建造者的方法来构建产品。指挥者知道如何组织和协调各个部件的构建过程,以确保按照正确的顺序完成。
3. 代码示例
3.1 示例1
- 建造者模式代码示例
/**
* 产品类
*/
class Product {
private String partA;
private String partB;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void show() {
System.out.println("Product: " + partA + ", " + partB);
}
}
/**
* 抽象建造者
*/
abstract class Builder {
protected Product product = new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract Product getResult();
}
/**
* 具体建造者
*/
class ConcreteBuilder extends Builder {
@Override
public void buildPartA() {
product.setPartA("PartA");
}
@Override
public void buildPartB() {
product.setPartB("PartB");
}
@Override
public Product getResult() {
return product;
}
}
// 指挥者
class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPartA();
builder.buildPartB();
return builder.getResult();
}
}
/**
* 客户端代码
*/
public class Client {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Product product = director.construct();
product.show();
}
}
3.2 示例二
- 实例代码
class MilkTea {
double price;
String topping = "cream";
String tea = "Common tea";
Integer suger = 100;
public MilkTea() {
this.price = 9.9;
}
public double getPrice() {
return this.price;
}
}
class LatteMilkTea extends MilkTea {
public LatteMilkTea() {
this.price = 10.9;
}
}
class IceCreamMilkTea extends MilkTea {
public IceCreamMilkTea() {
this.price = 11.9;
}
}
interface MilkteaBuilder {
void reset();
void addTopping();
void addTea();
void addSugerLevel();
MilkTea getProduct();
}
class LatteMilkTeaBuilder implements MilkteaBuilder {
private LatteMilkTea latteMilkTea;
@Override
public void reset() {
this.latteMilkTea = new LatteMilkTea();
}
@Override
public void addTopping() {
latteMilkTea.topping = "latte topping";
}
@Override
public void addTea() {
latteMilkTea.tea = "latte tea";
}
@Override
public void addSugerLevel() {
latteMilkTea.suger = 95;
}
@Override
public MilkTea getProduct() {
System.out.format("LatteMilkTea: %s %s %s\n", this.latteMilkTea.topping, this.latteMilkTea.tea, this.latteMilkTea.price);
return this.latteMilkTea;
}
}
class IceCreamMilkTeaBuilder implements MilkteaBuilder {
private IceCreamMilkTea iceCreamMilkTea;
@Override
public void reset() {
this.iceCreamMilkTea = new IceCreamMilkTea();
}
@Override
public void addTopping() {
iceCreamMilkTea.topping = "ice cream topping";
}
@Override
public void addTea() {
iceCreamMilkTea.tea = "ice cream tea";
}
@Override
public void addSugerLevel() {
iceCreamMilkTea.suger = 95;
}
@Override
public MilkTea getProduct() {
System.out.format("LatteMilkTea: %s %s %s\n", this.iceCreamMilkTea.topping, this.iceCreamMilkTea.tea, this.iceCreamMilkTea.price);
return this.iceCreamMilkTea;
}
}
class MilkTeaDirector {
private MilkteaBuilder milkteaBuilder;
public MilkTeaDirector(MilkteaBuilder milkteaBuilder) {
this.milkteaBuilder = milkteaBuilder;
}
public void changeBuiler(MilkteaBuilder milkteaBuilder) {
this.milkteaBuilder = milkteaBuilder;
}
public MilkTea makeMikeTea() {
this.milkteaBuilder.reset();
this.milkteaBuilder.addTopping();
this.milkteaBuilder.addTea();
this.milkteaBuilder.addSugerLevel();
return this.milkteaBuilder.getProduct();
}
public MilkTea make(String type) {
if ("Latte".equals(type)) {
this.changeBuiler(new LatteMilkTeaBuilder());
} else if ("IceCream".equals(type)) {
this.changeBuiler(new IceCreamMilkTeaBuilder());
}
return this.makeMikeTea();
}
}
public class MilkTeaShop {
public static void main(String[] args) {
MilkTeaDirector director = new MilkTeaDirector(new LatteMilkTeaBuilder());
director.makeMikeTea();
director.changeBuiler(new IceCreamMilkTeaBuilder());
director.makeMikeTea();
director.make("Latte");
director.make("IceCream");
}
}
4. 优缺点
- 主要作用
- 逐步创建复杂的对象
- 优点
- 封装性好:创建和使用分离,用户无需了解产品内部细节。
- 扩展性好:由于建造类之间相互独立,在一定程度上实现了解耦,易于扩展和维护。
- 创建复杂对象:能够创建由各种复杂部件组成的产品,对于构造过程复杂的对象尤为有用。
- 缺点
- 增加类数量:可能会产生多余的Builder对象,增加系统的复杂度。
- 修改困难:当产品内部发生变化时,可能需要相应地修改建造者,维护成本较高。
5. 应用场景
- 对象构造复杂:当一个对象有很多属性,且这些属性的设置和组合非常复杂时,可以使用建造者模式来简化对象的构建过程。
- 参数过多:如果一个类的构造函数参数超过四个,特别是当某些参数是可选的或有默认值时,建造者模式可以帮助避免构造函数过于臃肿。
- 分步创建:在需要分步骤创建复杂对象时,建造者模式可以将每一步创建过程封装在不同的方法中,使得创建过程更加清晰和灵活。
- 创建与使用分离:当希望将复杂对象的创建过程和使用过程分开时,建造者模式可以很好地实现这一目标,提高代码的可维护性和扩展性。
- 多种表示:如果同一个复杂对象有多种不同的表示或配置方式,建造者模式可以通过不同的构建过程来创建这些不同的表示。
- 顺序敏感:当对象的构建过程中调用顺序不同可能导致不同的结果时,建造者模式可以通过指导者(Director)来控制构建顺序,确保对象的正确构建。
6. JDK中的使用
- StringBuilder类:这是JDK中一个典型的建造者模式实现。通过连续调用append方法,我们可以链式地构建一个字符串对象。最终,通过调用toString方法,我们可以得到一个完整的字符串对象。
- MyBatis中的SqlSessionFactoryBuilder:MyBatis是一个广泛使用的持久层框架,它的SqlSessionFactoryBuilder类也使用了建造者模式。这个类提供了一种逐步配置并最终构建SqlSessionFactory对象的方法。
7. 建造者 VS 抽象工厂
建造者 | 抽象工厂 | |
---|---|---|
目的 | 构建复杂对象 | 创建一系列相关关联的对象 |
创建对象方式 | 多步骤创建 | 单一步骤创建 |
8. 注意事项
- 明确需求:在实现建造者模式之前,需要明确复杂对象的构建需求。
- 分清角色:清晰区分建造者、具体建造者、指挥者和产品的角色。
- 构建解耦:确保构建过程与产品表示分离,使得同样的构建过程可以创建不同的表示。
- 顺序重要:当产品的构建顺序很重要时,需要确保指挥者能够控制具体的构建步骤和顺序。
- 避免过度设计:如果产品内部变化不复杂,不需要定义过多的具体建造者。
标签:对象,创建,void,建造,模式,Override,设计模式,public From: https://blog.csdn.net/m0_51176516/article/details/137454537