概要介绍
Builder模式是一步一步创建一个复杂对象的创建型模式。它允许用户在不知道类内部细节的情况下,实现精细的对象创建过程控制。Builder模式可以将部件和组装过程分离开,使得构建过程和部件都可以扩展。
基本原理
Builder帮助我们通过逐个调用相应的API,一步步完成复杂产品的构建过程。Director类在实现中往往被省略,而是直接由用户使用Builder,配合链式调用来完成组装的过程。
UML类图
Computer 抽象产品类
Computer.Builder 抽象产品的Builder类
MacBook 具体产品类
MacBook.Builder 具体产品的Builder类
Director 负责统一装配过程
代码实现
package com.hello;
abstract class Computer {
public abstract void setDisplay(String display);
public abstract void setOs(String os);
public abstract void setBoard(String board);
@Override
public String toString() {
return "[board=" + board + ", os=" + os
+ ", display=" + display + "]";
}
static abstract class Builder {
public abstract void buildOs(String os);
public abstract void buildDisplay(String display);
public abstract void buildBoard(String board);
public abstract Computer create();
}
public String display;
public String os;
public String board;
}
class MacBook extends Computer {
@Override
public void setDisplay(String display) {
this.display = display;
}
@Override
public String toString() {
return "MacBook " + super.toString();
}
@Override
public void setOs(String os) {
if (!os.startsWith("Mac OS")) {
System.err.println("Invalid OS!");
return;
}
this.os = os;
}
@Override
public void setBoard(String board) {
this.board = board;
}
static class Builder extends Computer.Builder {
private Computer computer = new MacBook();
@Override
public void buildOs(String os) {
computer.setOs(os);
}
@Override
public void buildDisplay(String display) {
computer.setDisplay(display);
}
@Override
public void buildBoard(String board) {
computer.setBoard(board);
}
@Override
public Computer create() {
return computer;
}
}
}
class Director {
Computer.Builder builder = null;
public Director(Computer.Builder builder) {
this.builder = builder;
}
public void construct(String board, String os, String display) {
builder.buildBoard(board);
builder.buildOs(os);
builder.buildDisplay(display);
}
public Computer create() {
return builder.create();
}
}
/**
* Created by qunfeng on 2019/4/23.
*/
public class Test {
public static void main(String[] args) {
Director director = new Director(new MacBook.Builder());
director.construct("Micro board", "Mac OS 11.0", "LCD");
System.out.println(director.create().toString());
}
}
通常用法
在okhttp中,Request类有相应的用法。
package com.hello;
public class Vehicle {
enum Color{
BLACK,
WHITE,
GREEN,
RED,
}
Color mColor;
int mWheels;
String mDescription;
public Vehicle(Builder builder) {
mColor = builder.mColor;
mWheels = builder.mWheels;
mDescription = "Brand: " + builder.mBrand
+ ", Model: " + builder.mModel;
}
public String toString() {
return "Color: " + mColor
+ ", Wheels: " + mWheels
+ ", [" + mDescription + "]"
+ ", " + hashCode();
}
public static class Builder {
Color mColor;
int mWheels;
String mBrand;
String mModel;
public Builder(int wheels) {
mWheels = wheels;
mColor = null;
mBrand = null;
mModel = null;
}
public Builder setColor(Color color) {
mColor = color;
return this;
}
public Builder setBrand(String brand) {
mBrand = brand;
return this;
}
public Builder setModel(String model) {
mModel = model;
return this;
}
public Vehicle build() {
return new Vehicle(this);
}
}
}
package com.hello;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello HTTP!" );
Request request = new Request.Builder()
.url("http://www.baidu.com/")
.method("GET", null)
.build();
Call call = new OkHttpClient().newCall(request);
try {
Response response = call.execute();
if (response != null) {
Document document = Jsoup.parse(response.body().string());
if (document != null) {
System.out.println(document.title());
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Bye HTTP!");
System.out.println("Hello Vehicle!");
Vehicle vehicle = new Vehicle.Builder(4)
.setColor(Vehicle.Color.RED)
.setBrand("BMW")
.setModel("X1")
.build();
System.out.println(vehicle.toString());
System.out.println("Bye Vehicle!");
}
}
优劣分析
优点:1. 扩展产品类方便,无需修改构造函数。2. 可以详细控制产品构造过程。
缺点:消耗多,创建类对象的时候需要额外创建另一个类(Builder)对象。
其他分析