这个专题,我们将要学习一下设计模式,建造者模式——快速构建对象。
阅读目录:
- 什么是建造者模式;
- 建造者模式源码实战;
- 建造者模式lombok快速实现;
- 如何“万物皆可建造者”快速创建对象;
1. 什么是建造者模式
工厂模式实现:获取对象;
建造模式实现:创建对象;
建造模式利用一个导演者(Director)
和具体建造者(Builder)
对象,将所需的零件一个个建造出来,从而建造出完整的产品对象。建造者模式将产品结构和产品零件
的建造过程隐藏起来,把対建造过程进行指挥和具体建造者的责任分割开,达成责任划分和封装的目的。
2. 建造者模式源码实战
我们在设置BasicProperties()时候,是不是要写这么复杂的引用链代码,是不是有时候感觉到一脸蒙蔽?
public class MQBuilder {
public static void main(String[] args) {
// 一个是replyTo设置回调队列,另一是correlationId(相关性Id)为每个队列设置唯一值
AMQP.BasicProperties props = new AMQP.BasicProperties().builder().correlationId("XP123")
.replyTo("replyQueueName").build();
}
}
那好我们就可以分析一下源码了。
正如温故知新——内部类中,我们知道静态内部类对象的创建方式:
外部类.内部类 XX=new 外部类.内部类();
- 那么我们分析其实
BasicProperties
就是一个静态内部类,最后的build
方法【返回的Product
产品】也就是new AMQP.basicProperties(XXX)
,完成具体建造类
的功能之一:返回建造完毕产品对象。
public AMQP.BasicProperties build() {
return new AMQP.BasicProperties(this.contentType,
this.contentEncoding, this.headers, this.deliveryMode, this.priority,
this.correlationId, this.replyTo, this.expiration, this.messageId,
this.timestamp, this.type, this.userId, this.appId, this.clusterId);
}
- 我们继续看
new AMQP.BasicProperties().builder()
这个调用链,其实就是创建了内部静态内build
对象。
Builder
里面包含了零件信息,用户可以将自己需求传入到Builder
对象,实现实时传入到Director
的效果。
public static final class Builder {
private String contentType;
private String contentEncoding;
private Map<String, Object> headers;
private Integer deliveryMode;
private Integer priority;
private String correlationId;
...
public Builder() {
}
public AMQP.BasicProperties.Builder contentType(String contentType) {
this.contentType = contentType;
return this;
}
public AMQP.BasicProperties.Builder contentEncoding(String contentEncoding) {
this.contentEncoding = contentEncoding;
return this;
}
public AMQP.BasicProperties.Builder headers(Map<String, Object> headers) {
this.headers = headers;
return this;
}
public AMQP.BasicProperties.Builder deliveryMode(Integer deliveryMode) {
this.deliveryMode = deliveryMode;
return this;
}
...
public AMQP.BasicProperties build() {
return new AMQP.BasicProperties(this.contentType, this.contentEncoding, this.headers, this.deliveryMode, this.priority, this.correlationId, this.replyTo, this.expiration, this.messageId, this.timestamp, this.type, this.userId, this.appId, this.clusterId);
}
}
}
3. 建造者模式lombok快速实现
在lombok插件中使用@Builder注解,就可以为POJO提供建造者模式:
源代码:
@Builder(toBuilder = true)
@Getter
public class Address {
private String address;
private String phone;
}
class反编译文件
package com.protoType.MySchema;
public class Address
{
private String address;
private String phone;
Address(String address, String phone)
{
this.address = address; this.phone = phone; }
public static AddressBuilder builder() { return new AddressBuilder(); }
public AddressBuilder toBuilder() { return new AddressBuilder().address(this.address).phone(this.phone); }
public String getAddress() { return this.address; }
public String getPhone() { return this.phone;
}
public static class AddressBuilder
{
private String address;
private String phone;
public AddressBuilder address(String address)
{
this.address = address; return this; }
public AddressBuilder phone(String phone) { this.phone = phone; return this; }
public Address build() { return new Address(this.address, this.phone); }
public String toString() { return "Address.AddressBuilder(address=" + this.address + ", phone=" + this.phone + ")";
}
}
}
4. 如何“万物皆可建造者”快速创建对象
场景:不想每次使用Map的时候都要先new Map,然后一次次的put,那么就可以使用建造者模式来实现MapExample。
public class MapExample {
private MapExample() {
}
/**
* 快速创建Map对象
*/
public static MapExample.Builder builder() {
return new MapExample.Builder();
}
public static class Builder {
private Map<String, Object> map;
Builder() {
map = new HashMap<>();
}
public MapExample.Builder put(String key, Object value) {
map.put(key, value);
return this;
}
public MapExample.Builder putAll(Map<String, Object> objectMap) {
map.putAll(objectMap);
return this;
}
public Map<String, Object> build() {
return map;
}
}
}
使用方式:
Map<String, Object> map = MapExample.builder().
put("url", request.getURI().toString()).
put("header", request.getHeaders()).
put("body", new String(body)).
put("response", responseBody).
put("executeTime", System.currentTimeMillis() - startTime).
build();