建造者模式

建造者模式是将对象的构建封装起来解耦,方便调用者创建复杂的对象,无需知道构建的细节。

常见的使用场景就是一些复杂的连接对象,有非常多的配置,用户不可能清楚每一个属性,所以一般会通过建造者模式来提供属性的默认值,用户只需设置关键的属性,方便调用者使用。

在这里插入图片描述

下面根据nacos源码里的一个例子说明建造者模式

@Data
public class RestResult<T> implements Serializable {

    private static final long serialVersionUID = 6095433538316185017L;

    private int code;

    private String message;

    private T data;

    public RestResult() {
    }

    public RestResult(int code, String message, T data) {
        this.code = code;
        this.setMessage(message);
        this.data = data;
    }

    public RestResult(int code, T data) {
        this.code = code;
        this.data = data;
    }

    public RestResult(int code, String message) {
        this.code = code;
        this.setMessage(message);
    }

    public boolean ok() {
        return this.code == 0 || this.code == 200;
    }

    /**
     * 这里有一些简化,没有继承父类或接口,建造者模式实际可以有不同的实现子类
     */
    public static <T> ResResultBuilder<T> builder() {
        return new ResResultBuilder<T>();
    }

    public static final class ResResultBuilder<T> {

        private int code;

        private String errMsg;

        private T data;

        private ResResultBuilder() {
        }

        public ResResultBuilder<T> withCode(int code) {
            // 当然这里可以再添加一些复杂的逻辑,比如设置了某属性值,其他属性就只能为某些值
            this.code = code;
            return this;
        }

        public ResResultBuilder<T> withMsg(String errMsg) {
            this.errMsg = errMsg;
            return this;
        }

        public ResResultBuilder<T> withData(T data) {
            this.data = data;
            return this;
        }

        /**
         * Build result.
         *
         * @return result
         */
        public RestResult<T> build() {
            RestResult<T> restResult = new RestResult<T>();
            restResult.setCode(code);
            restResult.setMessage(errMsg);
            restResult.setData(data);
            return restResult;
        }
    }
}

下面相当于Director,用于指挥控制对象的创建

public class RestResultUtils {
    
    public static <T> RestResult<T> success() {
        return RestResult.<T>builder().withCode(200).build();
    }
    
    public static <T> RestResult<T> success(T data) {
        return RestResult.<T>builder().withCode(200).withData(data).build();
    }
    
    public static <T> RestResult<T> success(int code, T data) {
        return RestResult.<T>builder().withCode(code).withData(data).build();
    }
    
    public static <T> RestResult<T> failed() {
        return RestResult.<T>builder().withCode(500).build();
    }
    
    public static <T> RestResult<T> failed(int code, T data) {
        return RestResult.<T>builder().withCode(code).withData(data).build();
    }
    
}

应用举例

经常用来提供那些拥有复杂属性的对象,用户可以只设置自己关心的部分属性,如spring框架提供的很多连接对象。

下面拿构建RedisCacheManager的源码举例:

 @Bean
 RedisCacheManager redisCacheManager() {
 	 // 我们使用时只需要设置关键的属性即可
 	 return RedisCacheManager.RedisCacheManagerBuilder
 	 		.fromConnectionFactory(lettuceConnectionFactory)
            .withInitialCacheConfigurations(cacheConfigurationMap)
            .disableCreateOnMissingCache()
            .build();
 }

这里其实也是用到了建造者模式,

public class RedisCacheManager{

    private final RedisCacheWriter cacheWriter;
    private final RedisCacheConfiguration defaultCacheConfig;
    private final Map<String, RedisCacheConfiguration> initialCacheConfiguration;
    private final boolean allowInFlightCacheCreation;

 
    private RedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration,
                              boolean allowInFlightCacheCreation) {

        Assert.notNull(cacheWriter, "CacheWriter must not be null!");
        Assert.notNull(defaultCacheConfiguration, "DefaultCacheConfiguration must not be null!");

        this.cacheWriter = cacheWriter;
        this.defaultCacheConfig = defaultCacheConfiguration;
        this.initialCacheConfiguration = new LinkedHashMap<>();
        this.allowInFlightCacheCreation = allowInFlightCacheCreation;
    }

    protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) {
        return new RedisCache(name, cacheWriter, cacheConfig != null ? cacheConfig : defaultCacheConfig);
    }

  	// 通过builder来设置RedisCacheManager属性
    public static class RedisCacheManagerBuilder {

        private RedisCacheWriter cacheWriter;
        private RedisCacheConfiguration defaultCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        private final Map<String, RedisCacheConfiguration> initialCaches = new LinkedHashMap<>();
        private boolean enableTransactions;
        boolean allowInFlightCacheCreation = true;

        private RedisCacheManagerBuilder() {}

        private RedisCacheManagerBuilder(RedisCacheWriter cacheWriter) {
            this.cacheWriter = cacheWriter;
        }

        public static RedisCacheManagerBuilder fromConnectionFactory(RedisConnectionFactory connectionFactory) {
            return new RedisCacheManagerBuilder(new DefaultRedisCacheWriter(connectionFactory));
        }

        public static RedisCacheManagerBuilder fromCacheWriter(RedisCacheWriter cacheWriter) {
            return new RedisCacheManagerBuilder(cacheWriter);
        }

        public RedisCacheManagerBuilder cacheDefaults(RedisCacheConfiguration defaultCacheConfiguration) {
            Assert.notNull(defaultCacheConfiguration, "DefaultCacheConfiguration must not be null!");
            this.defaultCacheConfiguration = defaultCacheConfiguration;
            return this;
        }

        public RedisCacheManagerBuilder transactionAware() {
            this.enableTransactions = true;
            return this;
        }
   
        public RedisCacheManagerBuilder initialCacheNames(Set<String> cacheNames) {
            Assert.notNull(cacheNames, "CacheNames must not be null!");
            cacheNames.forEach(it -> withCacheConfiguration(it, defaultCacheConfiguration));
            return this;
        }

        public RedisCacheManagerBuilder withInitialCacheConfigurations(
            Map<String, RedisCacheConfiguration> cacheConfigurations) {
            Assert.notNull(cacheConfigurations, "CacheConfigurations must not be null!");
            cacheConfigurations.forEach((cacheName, configuration) -> Assert.notNull(configuration,
                String.format("RedisCacheConfiguration for cache %s must not be null!", cacheName)));
            this.initialCaches.putAll(cacheConfigurations);
            return this;
        }

        public RedisCacheManagerBuilder withCacheConfiguration(String cacheName, RedisCacheConfiguration cacheConfiguration) {
            Assert.notNull(cacheName, "CacheName must not be null!");
            Assert.notNull(cacheConfiguration, "CacheConfiguration must not be null!");
            this.initialCaches.put(cacheName, cacheConfiguration);
            return this;
        }
     
        public RedisCacheManagerBuilder disableCreateOnMissingCache() {
            this.allowInFlightCacheCreation = false;
            return this;
        } }

        public RedisCacheManager build() {
            Assert.state(cacheWriter != null, "CacheWriter must not be null! '.");
            RedisCacheManager cm = new RedisCacheManager(cacheWriter, defaultCacheConfiguration, initialCaches, allowInFlightCacheCreation);
            cm.setTransactionAware(enableTransactions);
            return cm;
        }
    }
}

优点

  • 易于解耦
    将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同属性的产品。
  • 易于精确控制对象的创建
    将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
  • 易于拓展
    增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。

每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。

缺点

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的属性差异性很大,则不适合使用建造者模式。
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值