1. 什么是生成器模式?
《Head First设计模式》中定义:封装一个产品的构造过程,并允许按步骤构造。
生成器模式(Builder Pattern)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。生成器模式是对象创建型模式,又叫建造者模式。
生成器模式针对的是复杂对象的创建。它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造不同表现(属性)的对象。
举个例子加深理解:
比如我们要去法拉利私人定制一款汽车,我们只需要向服务商提需求,然后服务商就会协调生产车间生产汽车。定制的汽车就是一个复杂的对象,其中包含空调系统、电子系统。动力系统等,而每一个子系统的生产都是复杂且非常耗时的。如果全部工作都交给一个车间来生产的话(传统创建对象),可能等我老了这个车还没造出来。如果将生产过程各自分工(创建过程抽象出来),然后由一个协调部门负责组装的话,这样汽车建造速度将大大提高,而且私人定制也比较容易(想怎么组装就怎么组装),装上普通动力系统的就是法拉利轿车,装上强劲动力系统就是法拉利跑车(不同的表现)。这个协调部门就是Director角色。
2. 角色
图片来源于网络
抽象建造者(Builder):可以是接口也可以是抽象类。为创建产品Product对象的各个组件指定抽象方法。一般有两类方法,一类是创建复杂对象的各个组件(buildPartA、buildPartB...)和另一类返回创建的复杂对象(getResult)。
具体建造者(ConcreteBuilder):Builder的具体实现类,可以有多个,每一个提供复杂对象各个组件的一种创建和装配方法,最终返回创建好的复杂对象。
产品角色(Product):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程
指挥者角色(Director):Director负责安排复杂对象Product的建造次序。Director和Builder存在关联关系,通过construct方法调用Builder中的创建方法完成复杂对象的创建。客户端只需要和Director联系。
3. 优点
(1)客户端不需要知道复杂对象的创建细节,将对象和创建过程解耦,使相同的创建过程可以创建不同的对象。
(2)每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可创建不同的产品对象。由于指挥者类针对抽象建造者编程,增加新的具体建造者无须修改原有代码,系统扩展方便,符合“开闭原则”。
(3)可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
4. 缺点
(1)使用生成器模式必须要求Product类具有相似的结构,如果差异性太大就无法使用该模式,因此具有一定的局限性。
(2)将创建过程抽象出来会造成类文件增加。
5. 使用场景
(1)要生成的产品对象有复杂的内部结构,包含多个成员属性。
(2)将创建过程分离开,使相同的创建过程能创建不同的产品对象。
(3)产品对象内部组件之间存在相互依赖,且组件创建具有一定的顺序。
6. 示例代码
(1)抽象建造者类
/**
*抽象建造者
*/
public abstract class AbstractCarBuilder {
//产品的引用
protected Car car;
public AbstractCarBuilder() {
this.car=new Car();
}
public abstract void buildAcSystem();
public abstract void buildPowerSystem();
public abstract void buildElectronicSystem();
public Car getCar(){
return car;
}
}
(2)具体建造者类
/**
* 普通汽车建造者
*/
public class LittleCarBuilder extends AbstractCarBuilder {
@Override
public void buildAcSystem() {
this.car.setAcSystem("海尔空调系统");
}
@Override
public void buildPowerSystem() {
this.car.setPowerSystem("1.6自然吸气系统");
}
@Override
public void buildElectronicSystem() {
this.car.setElectronicSystem("华为电子系统");
}
}
/**
* 跑车建造者
*/
public class SportsCarBuilder extends AbstractCarBuilder {
@Override
public void buildAcSystem() {
this.car.setAcSystem("格力空调系统");
}
@Override
public void buildPowerSystem() {
this.car.setPowerSystem("4.0T涡轮增压系统");
}
@Override
public void buildElectronicSystem() {
this.car.setElectronicSystem("西门子电子系统");
}
}
(3)产品类
/**
*产品类
*其中可能存在许多创建过程比较复杂的其他对象
*/
public class Car {
//空调系统组件(可以是一个对象)
private String acSystem;
//动力系统组件
private String powerSystem;
//电子系统组件
private String electronicSystem;
public String getAcSystem() {
return acSystem;
}
public void setAcSystem(String acSystem) {
this.acSystem = acSystem;
}
public String getPowerSystem() {
return powerSystem;
}
public void setPowerSystem(String powerSystem) {
this.powerSystem = powerSystem;
}
public String getElectronicSystem() {
return electronicSystem;
}
public void setElectronicSystem(String electronicSystem) {
this.electronicSystem = electronicSystem;
}
@Override
public String toString() {
return "Car [acSystem=" + acSystem + ", powerSystem=" + powerSystem + ", electronicSystem=" + electronicSystem
+ "]";
}
}
(4)指挥者类
/**
*car建造指挥者
*/
public class CarDirector {
private AbstractCarBuilder acb;
public CarDirector(AbstractCarBuilder acb) {
this.acb=acb;
}
public void setAcb(AbstractCarBuilder acb) {
this.acb = acb;
}
public Car constructCar(){
//此处可以规定组件创建顺序
acb.buildAcSystem();
acb.buildElectronicSystem();
acb.buildPowerSystem();
return acb.getCar();
}
}
(5)测试
public class Client {
public static void main(String[] args) {
CarDirector director=new CarDirector(new SportsCarBuilder());
Car car1=director.constructCar();
System.out.println(car1.toString());
System.out.println("---------------");
director.setAcb(new LittleCarBuilder());
Car car2=director.constructCar();
System.out.println(car2.toString());
}
}
(6)测试结果
Car [acSystem=格力空调系统, powerSystem=4.0T涡轮增压系统, electronicSystem=西门子电子系统]
---------------
Car [acSystem=海尔空调系统, powerSystem=1.6自然吸气系统, electronicSystem=华为电子系统]
7. 生成器模式和工厂模式的对比
图片来源于网络
【四川乐山程序员联盟,欢迎大家加群相互交流学习5 7 1 8 1 4 7 4 3】