简介
builder模式的使用目的是为了将构建复杂对象的过程和它的部件解耦。将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
Builder模式,在于分工明确,一个抽象建造者,一个具体的建造者,一个指挥者,当然还需要具体的产品。那么我们以一个软件产品为例:技术主管就是抽象建造者,他和产品经理沟通,知道要做一个什么样的产品;而程序员就是具体的劳动者,技术主管说咋做你就咋做;而指挥者就是公司的产品经理,负责和用户沟通,了解客户的需求。
适用性
相同的方法,不同的执行顺序,产生不同的事件结果时;
多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时;
产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适;
当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时。
2 Builder模式UML类图通用
角色介绍:
Product——产品类 : 产品的抽象类。
Builder——抽象类, 规范产品的组建,一般是由子类实现具体的组件过程。
ConcreteBuilder——具体的构建者。
Director——指挥者,统一组装过程(可省略)。
Builder模式变种(常用
1 普通
public class Person {
private String name;
private int age;
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
创建各个需要的对象:
Person p1=new Person();
Person p2=new Person("张三");
Person p3=new Person("李四",18);
可以想象一下这样创建的坏处,最直观的就是四个参数的构造函数的最后面的两个参数到底是什么意思,可读性不怎么好,如果不点击看源码,不知道哪个是weight哪个是height。还有一个问题就是当有很多参数时,编写这个构造函数就会显得异常麻烦,这时候如果换一个角度,试试Builder模式,你会发现代码的可读性一下子就上去了。4.2 使用Builder模式
public class Person {
private String name;
private int age;
private Person(Builder builder){
this.name=builder.name;
this.age=builder.age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
static class Builder{
private String name;
private int age;
public Builder setName(String name) {
this.name=name;
return this;
}
public Builder setAge(int age) {
this.age=age;
return this;
}
eturn this;
}
public Person build(){
return new Person(this);// build()返回Person对象
}
}
}
在Builder类里定义了一份与Person类一模一样的变量,通过一系列的成员函数进行设置属性值,但是返回值都是this,也就是都是Builder对象,最后提供了一个build函数用于创建Person对象,返回的是Person对象,对应的构造函数在Person类中进行定义,也就是构造函数的入参是Builder对象,然后依次对自己的成员变量进行赋值,对应的值都是Builder对象中的值。此外Builder类中的成员函数返回Builder对象自身的另一个作用就是让它支持链式调用,使代码可读性大大增强。于是可以这样创建Person类。
Person person = new Person().Builder()
.setName("张三")
.setAge(18)
.setHeight(178.5)
.setWeight(67.4)
.build();
4.3 总结一下
(1)定义一个静态内部类Builder,内部的成员变量和外部类一样
Builder类通过一系列的方法用于成员变量的赋值,并返回当前对象本身(this)。
(2)Builder类提供一个build方法或者create方法用于创建对应的外部类,该方法内部调用了外部类的一个私有构造函数,该构造函数的参数就是内部类Builder。
(3)外部类提供一个私有构造函数供内部类调用,在该构造函数中完成成员变量的赋值,取值为Builder对象中对应的值。
2 Builder模式实战
(1)产品类——探探App/**
* 产品类——探探App
*/
public class Product {
public static final String ANDROID = "android";
public static final String IOS = "ios";
private String appName;
private String appFuction;
private String appSystem;
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getAppFuction() {
return appFuction;
}
public void setAppFuction(String appFuction) {
this.appFuction = appFuction;
}
public String getAppSystem() {
return appSystem;
}
public void setAppSystem(String appSystem) {
this.appSystem = appSystem;
}
@Override
public String toString() {
return "Product [appName=" + appName + ", appFuction=" + appFuction
+ ", appSystem=" + appSystem + "]";
}
}
(2)抽象建造者类——技术主管(可省略)/**
* 抽象建造者类——技术主管
*/
public abstract class Build {
public abstract Build setAppName(String appName);
public abstract Build setAppFuction(String appFuction);
public abstract Build setAppSystem(String appSystem);
public abstract Product build();
}
(3)具体建造者类——全栈程序员/**
* 具体建造者类——全栈程序员
*/
public class WorkBuilder extends Build {
private Product product;// 产品类
private InnerProduct innerProduct = new InnerProduct();// 产品缓冲类
@Override
public Build setAppName(String appName) {
innerProduct.setAppName(appName);
return this;
}
@Override
public Build setAppFuction(String appFuction) {
innerProduct.setAppFuction(appFuction);
return this;
}
@Override
public Build setAppSystem(String appSystem) {
innerProduct.setAppSystem(appSystem);
return this;
}
@Override
public Product build() {
product = new Product();
product.setAppName(innerProduct.getAppName());
product.setAppFuction(innerProduct.getAppFuction());
product.setAppSystem(innerProduct.getAppSystem());
return product;
}
/**
* 产品缓冲类
*/
private class InnerProduct {
private String appName;
private String appFuction;
private String appSystem;
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getAppFuction() {
return appFuction;
}
public void setAppFuction(String appFuction) {
this.appFuction = appFuction;
}
public String getAppSystem() {
return appSystem;
}
public void setAppSystem(String appSystem) {
this.appSystem = appSystem;
}
}
}
(4)指挥者类——产品经理(可省略)
/**
* 指挥者类——产品经理
*/
public class Director {
public static Product create(String system) {
return new WorkBuilder().setAppSystem(system).setAppName("探探").setAppFuction("划一划找妹子").build();
}
}
(5)客户端——客户/**
* 客户端——客户
public class Client {
public static void main(String[] args){
// 客户:我需要一个可以摇一摇找妹子的软件
// 产品经理:分析得出就做一个探探
// 技术主管:appName:探探,系统:ios,android功能:摇一摇找妹子
Product android = Director.create(Product.ANDROID);
Product ios = Director.create(Product.IOS);
System.out.println(android);
System.out.println(ios);
/**
* 变异来的建造者可以只需要具体建造者,抽象的不要了,指挥者也可以不要了
*/
// 程序员觉得太累了,工资又少,干的最多,最后决定自己出去单干。
WorkBuilder niubiProgremer = new WorkBuilder();
Product androidBest = niubiProgremer.setAppName("探探").setAppSystem(Product.ANDROID).setAppFuction("摇一摇,找妹子").build();
Product iosBest = niubiProgremer.setAppName("探探").setAppSystem(Product.IOS).setAppFuction("摇一摇,找妹子").build();
System.out.println("-------------------------------------------------------------------------------------");
System.out.println(androidBest);
System.out.println(iosBest);
}
}
(6)结果
Product [appName=探探, appFuction=划一划找妹子, appSystem=android]
Product [appName=探探, appFuction=划一划找妹子, appSystem=ios]
-------------------------------------------------------------------------------------
Product [appName=探探, appFuction=摇一摇,找妹子, appSystem=android]
Product [appName=探探, appFuction=摇一摇,找妹子, appSystem=ios]