03-建造者模式

03-建造者模式

1.未使用建造者模式创建对象

  1. 未使用建造者模式创建对象存在的问题。
    1. 将name必填项放入构造函数中,如果必填项过多就会导致构造函数参数列表过长。如果不把必填项放入构造函数中,而是通过setter方法进行设置,那么必填项是否已经填写的校验逻辑就无处安放了。
    2. 假设配置项之间有一定的约束条件,如maxIdle、minIdle必须小于或等于maxTotal。如果通过setter方法设置配置项,那么配置项之间的依赖关系或约束关系的校验逻辑就无处安放了。
    3. 如果希望ResourcePoolConfig类是不可变对象,即ResourcePoolConfig对象在创建完成之后就不能修改内部属性的值,就不能在ResourcePoolConfig类中暴露setter方法。
  2. 未使用建造者模式创建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.使用建造者模式创建对象

  1. 使用内部类Builder来创建ResourcePoolConfig类;将参数的校验逻辑放入到build方法中,build方法进行所有参数的校验;ResourcePoolConfig只提供getter方法,不提供setter方法,避免了对ResourcePoolConfig类的修改。

  2. 使用建造者模式创建对象代码。

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.建造者模式总结

  1. 建造者模式的使用场景。当创建的对象较为复杂,需要指定多个参数,并且需要对多个参数进行多种逻辑校验时,可以使用建造者模式来完成。
  2. 建造者模式和工厂模式的区别。
    1. 工厂模式用来创建类型不同但是相关的对象(继承同一个父类或者接口的同一组子类),由给定的参数来决定创建哪种类型的对象。
    2. 建造者模式用来创建同一种类型的复杂对象,通过设置不同的参数,定制化创建不同的对象。

4.建造者模式在Java中的应用

  1. 建造者模式在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();
    }
}
posted @ 2022-11-25 11:56  行稳致远方  阅读(21)  评论(0)    收藏  举报