在软件开发过程中有时需要创建一个复杂的对象,这个复杂对象通常由多个子部件按一定的步骤组合而成。例如:在新招收一个员工时,对个人信息对象的创建,在不同的阶段,需要个人信息的内容也不一样,姓名、性别、年龄等等这些基本的信息在一开始就要被创建,但是当加入公司后会有其它其它属性,如:行政级别、公司邮箱、工资等属性 时,就需要后期对其添加。
对于这种对象的创建,我们不能再用前面的工厂方法模式对其创建了,只有建造者模式才可以更好的描述和创建此类对象。
一.介绍
定义:
指将一个复杂对象的构造与它持有的属性分离,使同样的构建过程可以创建不同的属性的对象,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象创建,。它将变与不变相分离,即对象的组成部分是不变的,但是创建对象的每一个属性都是可以灵活选择的。
优点:
各个具体的建造者相互独立,有利于系统的扩展。
客户端不必知道产品内部组成的细节,便于控制细节风险。
缺点:
对象的组成部分必须相同,这限制了其使用范围。
如果对象的内部变化复杂,该模式会增加很多的建造者类。
建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。
总述:
在不同阶段创建不同的对象属性
结构
对象原型 (Persion): 原始对象所具有的多种属性,这个可以结合业务属性来定义
建造者角色(Builder): 它是一个要创建对象原型的内部类,它有与对象原型相同的属性,有创建初始对象的构造方法,并且还有一个返回原型对象的builder方法
二.实现原理
通过访问静态内部的形式得到内部类,内部类通过有参方法将传入的参数赋值给静态内部类对象,外部类私有构造函数,参数设置成静态内部类对象当静态内部类对象通过无参的build方法获得外部类时,外部类构造函数需要传入静态内部类实例对象,此时,精彩的来了,因为通过访问静态内部的方法获得了内部类对象,而在调用build方法时需要传入内部类对象,而在外部类的私有构造中传入的是静态内部类对象,因此build方法之前全是静态内部类对象,而在build时,确将自己当成参数传入外部类的构造函数中,通过外部类的构造函数里的赋值,得到了外部类对象的实例。
仔细想想,将自己当成参数传入确实精彩
三.应用场景
当要创建的对象一次不能完全初始化完成,有的属性需要通过后期才能将其初始化完成的,可以用此设计模式
四.代码实现
//原型对象
public class Persion { private String name; //姓名 private int age; //年龄 private String gender; //性别 private String email; //邮箱 private String level; //行政级别 private double salary; //工资 public Persion (Builder builder) { this.name = builder.name; this.age = builder.age; this.gender = builder.gender; this.email = builder.email; this.level = builder.level; this.salary = builder.salary; } public Persion email(String email) { this.email = email; return this; } public Persion level(String level) { this.level = level; return this; } public Persion salary(double salary) { this.salary = salary; return this; } @Override public String toString() { return "Persion [name=" + name + ", age=" + age + ", gender=" + gender + ", email=" + email + ", level=" + level + ", salary=" + salary + "]"; } //实际建造者对象 static class Builder{ private String name; //姓名 private int age; //年龄 private String gender; //性别 private String email; //邮箱 private String level; //行政级别 private double salary; //工资 public Builder(String name, int age, String gender) { this.name = name; this.age = age; this.gender = gender; } public Persion builder() { //这个方法相当精彩,哪个要创建的对象调用builder方法,就将自己作为参数去构造persion对象 return new Persion(this); } } }
测试类
public class BuilderPattern { public static void main(String[] args) { //入职前张三的基本信息 Persion builder = new Persion.Builder("张三",23,"男").builder(); System.out.println("加入公司之前 : "+builder); //入职后张三的附加信息 builder.email("123@qq.com").level("hight-level").salary(10000.0); System.out.println("加入公司之后 : "+builder); } }