模式意图
将一个复杂对象的构建和表示分离,使得同样的构建过程可以创建不同的表示
模式结构
代码示例
class Person {
private int id;
private String name;
private int age;
private String sex;
private String score;
private AddressInfo addressInfo;
private Person() {};
static class PersonBuilder {
Person person = new Person();
public PersonBuilder basicInfo(int id, String name, int age) {
person.id = id;
person.name = name;
person.age = age;
return this;
}
public PersonBuilder addressInfo(String street) {
person.addressInfo = new AddressInfo(street);
return this;
}
public PersonBuilder otherInfo(String sex, String score) {
person.sex = sex;
person.score = score;
return this;
}
public Person build() {
return person;
}
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + ''' +
", age=" + age +
", sex='" + sex + ''' +
", score='" + score + ''' +
", addressInfo=" + addressInfo +
'}';
}
}
class AddressInfo {
String street;
public AddressInfo(String street) {
this.street = street;
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person.PersonBuilder().basicInfo(1, "gao", 25).build();
System.out.println(person.toString());
}
}
适用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性(避免构造函数的重载,假设你的构造函数中有十几个可选参数,调用该函数就会非常的不方便,可能需要重载生成几个简化版的构造函数)
- 需要生成的产品对象的属性互相依赖,需要指定其生成顺序
- 对象的创建过程独立于创建该对象的类。在生成器模式中引入指挥者类,将创建过程封装在指挥者类中,而不在生成器类中
- 隔离复杂对象的创建和使用,并使得同样的创建过程可以创建不同的产品(例如建造石头房和木房子,创建过程是一致的,但是生成最终的产品是不同的)
场景案例
- 很多游戏软件中,地图包括天空、地面、背景等组成部分,可以使用生成器模式进行设计,从而生成不同种类的地图
模式效果(优缺点)
- 可以更加精细地控制产品的创建过程,你可以分步创建对象,暂缓创建步骤或者递归运行创建步骤
- 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以生成不同的产品对象(生成不同形式的产品时,可以复用相同的构建过程)
- 每一个具体的生成器都相对独立,可以很方便的替换不同的生成器以生成不同的产品对象
- 新增新的生成器不需要修改原有的代码,指挥者类针对抽象生成器进行编程,符合开闭原则
- 生成器模式所创建的产品虽然种类不同,但是他们的构建流程很相似,如果产品之间差异较大,则不适用使用该模式
- 如果产品内部变化很复杂,可能需要定义很多个具体的生成器来实现这种变化,进而导致系统变得复杂
模式扩展
- 与抽象工厂相比,生成器模式返回一个组装好的完整产品;而抽象工厂是返回一系列相关产品,这些产品位于不同的等级结构,构成一个产品族
- 在抽象工厂中,客户端实例化具体的工厂类,然后调用工厂方法获取所需的产品;而在生成器模式中,客户端不直接调用生成器的相关方法,而是通过指挥者类而指导如何生成对象,它侧重于一步步生成一个复杂对象
- 如果将抽象工厂模式看作一个生成汽车配件生产工厂;那么生成器模式就是汽车组装工厂,通过对部件的组装生成一辆完成的汽车
- 抽象工厂重点在于生成一系列相关对象;生成器模式重点在于如何分步生成复杂对象。抽象工厂会马上返回产品对象;生成器模式则允许你在获取产品前执行一些额外构造步骤
- 你可以在创建复杂组合树时使用生成器,因为这可使其构造步骤以递归的方式运行
- 你可以结合使用生成器和桥接模式:主管类负责抽象工作,各种不同的生成器负责实现工作