1. 建造者模式的定义与优缺点
- 建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。建造者模式属于
创建型
设计模式,它是将一个复杂的对象分解为多个简单的对象,使用多个简单的对象一步一步构建成一个复杂的对象。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。 - 优点:
- 产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 各个具体的建造者相互独立,有利于系统的扩展。
- 客户端不必知道产品内部组成的细节,便于控制细节风险。
- 缺点:
- 产品的组成部分必须相同,这限制了其使用范围。
- 如果产品的内部变化复杂,该模式会增加很多的建造者类。
建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。
2. 创建者模式的结构
建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成,现在我们来分析其基本结构和实现方法。
建造者(Builder)模式的主要角色如下。
- 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个部件。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者(Director):指挥者针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象。该类的作用主要有两个:一方面它隔离了客户与生产过程;另一方面它负责控制产品的生成过程。
3. 使用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
- 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类中。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
4. 具体案例
-
产品角色:
public class Car { private String name; private double price; private String manufacturer; private int power; public void setName(String name) { this.name = name; } public void setPrice(double price) { this.price = price; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public void setPower(int power) { this.power = power; } @Override public String toString() { return "Car{" + "name='" + name + '\'' + ", price=" + price + ", manufacturer='" + manufacturer + '\'' + ", power=" + power + '}'; } }
-
抽象建造者:
public abstract class CarBuilder { protected Car car = new Car(); public abstract void buildName(); public abstract void buildPrice(); public abstract void buildManufacturer(); public abstract void buildPower(); public Car getResult(){ return car; } }
-
具体建造者:
public class BMWBuilder extends CarBuilder{ @Override public void buildName() { car.setName("宝马"); } @Override public void buildPrice() { car.setPrice(100); } @Override public void buildManufacturer() { car.setManufacturer("华晨宝马"); } @Override public void buildPower() { car.setPower(200); } }
-
指导者:
public class CarDirector { public static void generateCar(CarBuilder carBuilder){ carBuilder.buildName(); carBuilder.buildPower(); carBuilder.buildPrice(); carBuilder.buildManufacturer(); Car result = carBuilder.getResult(); System.out.println(result); } public static void main(String[] args) { //Car{name='宝马', price=100.0, manufacturer='华晨宝马', power=200} generateCar(new BMWBuilder()); } }
5. 模式的拓展
-
建造者(Builder)模式在应用过程中可以根据需要改变,如果创建的产品种类只有一种,只需要一个具体建造者,这时可以省略掉抽象建造者,甚至可以省略掉指挥者角色。
-
public class ApplePhone { private String name; private double price; private String color; public ApplePhone(ApplePhoneBuilder applePhoneBuilder) { this.name = applePhoneBuilder.name; this.price = applePhoneBuilder.price; this.color = applePhoneBuilder.color; } public static class ApplePhoneBuilder { private String name; private double price; private String color; public ApplePhoneBuilder setName(String name) { this.name = name; return this; } public ApplePhoneBuilder setPrice(double price) { this.price = price; return this; } public ApplePhoneBuilder setColor(String color) { this.color = color; return this; } public ApplePhone build() { return new ApplePhone(this); } } }
public class Test { public static void main(String[] args) { ApplePhone applePhone = new ApplePhone.ApplePhoneBuilder() .setColor("黑色") .setName("锤子手机") .setPrice(200) .build(); System.out.println(applePhone); //ApplePhone{name='锤子手机', price=200.0, color='黑色'} } }
-
实现思路:
- 目标角色中提供一个静态内部类,静态内部类中包含目标角色的所有字段,并且该静态内部类将作为目标角色的构造器的参数。
- 在静态内部类中编写字段的setter方法,返回值为该静态内部类(用于链式编程)。
- 在静态内部类中提供一个build方法,调用目标角色的构造函数,并将静态内部类作为参数提供给目标角色的构造器。
- 指导者按照一定的步骤调用静态内部类中的方法构造目标角色。
-
参考博客: