当前位置:网站首页>Builder pattern

Builder pattern

2022-06-11 21:33:00 Spicy chicken~

Why the constructor pattern is needed ?


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 (StringUtils.isBlank(name)) {
    
      throw new IllegalArgumentException("name should not be empty.");
    }
    this.name = name;
  }

  public void setMaxTotal(int maxTotal) {
    
    if (maxTotal <= 0) {
    
      throw new IllegalArgumentException("maxTotal should be positive.");
    }
    this.maxTotal = maxTotal;
  }

  public void setMaxIdle(int maxIdle) {
    
    if (maxIdle < 0) {
    
      throw new IllegalArgumentException("maxIdle should not be negative.");
    }
    this.maxIdle = maxIdle;
  }

  public void setMinIdle(int minIdle) {
    
    if (minIdle < 0) {
    
      throw new IllegalArgumentException("minIdle should not be negative.");
    }
    this.minIdle = minIdle;
  }
  //... Omit getter Method ...
}


// ResourcePoolConfig Use examples 
ResourcePoolConfig config = new ResourcePoolConfig("dbconnectionpool");
config.setMaxTotal(16);
config.setMaxIdle(8);

If we still need to solve the following three problems in the above code :
1. What we just said name Are mandatory , So we put it in the constructor , Force objects to be set when they are created . But if there are many required items , This will result in a long parameter list , If we put set Method , Then the logic to check whether these required items have been filled in is nowhere to be placed .
2. besides , Assume that there are certain dependencies between configuration items , such as , If the user has set maxTotal、maxIdle、minIdle One of them , You must explicitly set the other two ; Or there are certain constraints between configuration items , such as ,maxIdle and minIdle Less than or equal to maxTotal. If we continue to use the current design ideas , Then there is no place for the verification logic of the dependencies or constraints between these configuration items .
3. If we want to ResourcePoolConfig Class objects are immutable objects , in other words , After the object is created , You can no longer modify the internal attribute value . To implement this function , We can't be in ResourcePoolConfig Exposure in class set() Method .

The above problem is solved by the following code :
By creating a builder inner class , Then the builder sets set Method , also set The return value of the method is the constructor , Finally, check whether the logic is correct through the constructor .


public class ResourcePoolConfig {
    
  private String name;
  private int maxTotal;
  private int maxIdle;
  private int minIdle;

  private ResourcePoolConfig(Builder builder) {
    
    this.name = builder.name;
    this.maxTotal = builder.maxTotal;
    this.maxIdle = builder.maxIdle;
    this.minIdle = builder.minIdle;
  }
  //... Omit getter Method ...

  // We will Builder Class is designed to ResourcePoolConfig The inner class of .
  // We can also put Builder Class is designed as a separate non inner class ResourcePoolConfigBuilder.
  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() {
    
      //  Put the verification logic here to do , Including required items 、 Dependency verification 、 Constraint verification, etc 
      if (StringUtils.isBlank(name)) {
    
        throw new IllegalArgumentException("...");
      }
      if (maxIdle > maxTotal) {
    
        throw new IllegalArgumentException("...");
      }
      if (minIdle > maxTotal || minIdle > maxIdle) {
    
        throw new IllegalArgumentException("...");
      }

      return new ResourcePoolConfig(this);
    }

    public Builder setName(String name) {
    
      if (StringUtils.isBlank(name)) {
    
        throw new IllegalArgumentException("...");
      }
      this.name = name;
      return this;
    }

    public Builder setMaxTotal(int maxTotal) {
    
      if (maxTotal <= 0) {
    
        throw new IllegalArgumentException("...");
      }
      this.maxTotal = maxTotal;
      return this;
    }

    public Builder setMaxIdle(int maxIdle) {
    
      if (maxIdle < 0) {
    
        throw new IllegalArgumentException("...");
      }
      this.maxIdle = maxIdle;
      return this;
    }

    public Builder setMinIdle(int minIdle) {
    
      if (minIdle < 0) {
    
        throw new IllegalArgumentException("...");
      }
      this.minIdle = minIdle;
      return this;
    }
  }
}

//  This code will throw IllegalArgumentException, because minIdle>maxIdle
ResourcePoolConfig config = new ResourcePoolConfig.Builder()
        .setName("dbconnectionpool")
        .setMaxTotal(16)
        .setMaxIdle(10)
        .setMinIdle(12)
        .build();
原网站

版权声明
本文为[Spicy chicken~]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/162/202206112126375399.html