03-建造者模式
03-建造者模式
1.未使用建造者模式创建对象
- 未使用建造者模式创建对象存在的问题。
- 将name必填项放入构造函数中,如果必填项过多就会导致构造函数参数列表过长。如果不把必填项放入构造函数中,而是通过setter方法进行设置,那么必填项是否已经填写的校验逻辑就无处安放了。
- 假设配置项之间有一定的约束条件,如maxIdle、minIdle必须小于或等于maxTotal。如果通过setter方法设置配置项,那么配置项之间的依赖关系或约束关系的校验逻辑就无处安放了。
- 如果希望ResourcePoolConfig类是不可变对象,即ResourcePoolConfig对象在创建完成之后就不能修改内部属性的值,就不能在ResourcePoolConfig类中暴露setter方法。
- 未使用建造者模式创建ResourcePoolConfig对象。
public class ResourcePoolConfig {
private static final int DEFAULT_MAX_TOTAL = 8;
private static final int DEFAULT_MAX_IDLE = 8;
private static final int DEFAULT_MIN_IDLE = 0;
private String name;
private int maxTotal = DEFAULT_MAX_TOTAL;
private int maxIdle = DEFAULT_MAX_IDLE;
private int minIdle = DEFAULT_MIN_IDLE;
public ResourcePoolConfig(String name) {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("name is empty.");
}
this.name = name;
}
public void setMaxTotal(int maxTotal) {
if (maxTotal <= 0) {
throw new IllegalArgumentException("maxTotal <= 0.");
}
this.maxTotal = maxTotal;
}
public void setMaxIdle(int maxIdle) {
if (maxIdle < 0) {
throw new IllegalArgumentException("maxIdle < 0.");
}
this.maxIdle = maxIdle;
}
public void setMinIdle(int minIdle) {
if (minIdle < 0) {
throw new IllegalArgumentException("minIdle < 0.");
}
this.minIdle = minIdle;
}
}
public class Test {
public static void main(String[] args) {
ResourcePoolConfig resourcePoolConfig = new ResourcePoolConfig("myPool");
resourcePoolConfig.setMaxTotal(16);
resourcePoolConfig.setMaxIdle(16);
}
}
2.使用建造者模式创建对象
-
使用内部类Builder来创建ResourcePoolConfig类;将参数的校验逻辑放入到build方法中,build方法进行所有参数的校验;ResourcePoolConfig只提供getter方法,不提供setter方法,避免了对ResourcePoolConfig类的修改。
-
使用建造者模式创建对象代码。
public class ResourcePoolConfig {
private String name;
private int maxTotal;
private int maxIdle;
private int minIdle;
public String getName() {
return name;
}
public int getMaxTotal() {
return maxTotal;
}
public int getMaxIdle() {
return maxIdle;
}
public int getMinIdle() {
return minIdle;
}
private ResourcePoolConfig(Builder builder) {
this.name = builder.name;
this.maxTotal = builder.maxTotal;
this.maxIdle = builder.maxIdle;
this.minIdle = builder.minIdle;
}
public static class Builder {
private static final int DEFAULT_MAX_TOTAL = 8;
private static final int DEFAULT_MAX_IDLE = 8;
private static final int DEFAULT_MIN_IDLE = 0;
private String name;
private int maxTotal = DEFAULT_MAX_TOTAL;
private int maxIdle = DEFAULT_MAX_IDLE;
private int minIdle = DEFAULT_MIN_IDLE;
public ResourcePoolConfig build() {
// 校验逻辑放到build中,包括必填校验、依赖关系校验、约束条件校验等。
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("name not empty.");
}
if (maxIdle > maxTotal) {
throw new IllegalArgumentException("maxIdle > maxTotal.");
}
if (minIdle > maxTotal || minIdle > maxIdle) {
throw new IllegalArgumentException("minIdle > maxTotal || minIdle > maxIdle.");
}
return new ResourcePoolConfig(this);
}
public Builder setName(String name) {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("name not empty.");
}
this.name = name;
return this;
}
public Builder setMaxTotal(int maxTotal) {
if (maxTotal <= 0) {
throw new IllegalArgumentException("maxTotal <= 0.");
}
this.maxTotal = maxTotal;
return this;
}
public Builder setMaxIdle(int maxIdle) {
if (maxIdle < 0) {
throw new IllegalArgumentException("maxIdle < 0.");
}
this.maxIdle = maxIdle;
return this;
}
public Builder setMinIdle(int minIdle) {
if (minIdle < 0) {
throw new IllegalArgumentException("minIdle < 0");
}
this.minIdle = minIdle;
return this;
}
}
}
public class Test {
public static void main(String[] args) {
ResourcePoolConfig resourcePoolConfig = new ResourcePoolConfig.Builder()
.setName("myPool")
.setMaxTotal(10)
.setMaxIdle(10)
.setMinIdle(10)
.build();
System.out.println(resourcePoolConfig);
}
}
3.建造者模式总结
- 建造者模式的使用场景。当创建的对象较为复杂,需要指定多个参数,并且需要对多个参数进行多种逻辑校验时,可以使用建造者模式来完成。
- 建造者模式和工厂模式的区别。
- 工厂模式用来创建类型不同但是相关的对象(继承同一个父类或者接口的同一组子类),由给定的参数来决定创建哪种类型的对象。
- 建造者模式用来创建同一种类型的复杂对象,通过设置不同的参数,定制化创建不同的对象。
4.建造者模式在Java中的应用
- 建造者模式在guava缓存池创建中的使用。
public class Test {
public static void main(String[] args) {
/*
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
*/
Cache<Object, Object> build = CacheBuilder.newBuilder()
.initialCapacity(100)
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
}
}