生成器模式(Builder)——对象创建型模式

365 阅读4分钟

模式意图

将一个复杂对象的构建和表示分离,使得同样的构建过程可以创建不同的表示

模式结构

image.png

代码示例

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());
    }
}

适用场景

  1. 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性(避免构造函数的重载,假设你的构造函数中有十几个可选参数,调用该函数就会非常的不方便,可能需要重载生成几个简化版的构造函数)
  2. 需要生成的产品对象的属性互相依赖,需要指定其生成顺序
  3. 对象的创建过程独立于创建该对象的类。在生成器模式中引入指挥者类,将创建过程封装在指挥者类中,而不在生成器类中
  4. 隔离复杂对象的创建和使用,并使得同样的创建过程可以创建不同的产品(例如建造石头房和木房子,创建过程是一致的,但是生成最终的产品是不同的)

场景案例

  1. 很多游戏软件中,地图包括天空、地面、背景等组成部分,可以使用生成器模式进行设计,从而生成不同种类的地图

模式效果(优缺点)

  1. 可以更加精细地控制产品的创建过程,你可以分步创建对象,暂缓创建步骤或者递归运行创建步骤
  2. 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以生成不同的产品对象(生成不同形式的产品时,可以复用相同的构建过程)
  3. 每一个具体的生成器都相对独立,可以很方便的替换不同的生成器以生成不同的产品对象
  4. 新增新的生成器不需要修改原有的代码,指挥者类针对抽象生成器进行编程,符合开闭原则
  5. 生成器模式所创建的产品虽然种类不同,但是他们的构建流程很相似,如果产品之间差异较大,则不适用使用该模式
  6. 如果产品内部变化很复杂,可能需要定义很多个具体的生成器来实现这种变化,进而导致系统变得复杂

模式扩展

  1. 抽象工厂相比,生成器模式返回一个组装好的完整产品;而抽象工厂是返回一系列相关产品,这些产品位于不同的等级结构,构成一个产品族
  2. 抽象工厂中,客户端实例化具体的工厂类,然后调用工厂方法获取所需的产品;而在生成器模式中,客户端不直接调用生成器的相关方法,而是通过指挥者类而指导如何生成对象,它侧重于一步步生成一个复杂对象
  3. 如果将抽象工厂模式看作一个生成汽车配件生产工厂;那么生成器模式就是汽车组装工厂,通过对部件的组装生成一辆完成的汽车
  4. 抽象工厂重点在于生成一系列相关对象;生成器模式重点在于如何分步生成复杂对象。抽象工厂会马上返回产品对象;生成器模式则允许你在获取产品前执行一些额外构造步骤
  5. 你可以在创建复杂组合树时使用生成器,因为这可使其构造步骤以递归的方式运行
  6. 你可以结合使用生成器桥接模式:主管类负责抽象工作,各种不同的生成器负责实现工作