【从优秀源码中学习设计模式】--- 建造者模式

前言

本文以Java语言为主,分析包括JDK、Spring、MyBatis、Guava等一些优秀的开源代码、项目,在这些开源代码、项目中都包含了大量的设计模式,通过对它们进行分析,能够快速帮助我们学会设计模式的使用方式,由理论过渡到实践中,进而真正了解设计模式的思想,由于内容较多,所以每个设计模式单独写一篇文章,需要了解其他模式请点击对应链接跳转。

装饰器模式
适配器模式
策略模式
模板模式

建造者模式

JDK

Calendar这个类提供了通过建造者模式构建对象的方式
在这里插入图片描述

public Calendar build() {
    
    
    if (locale == null) {
    
    
        locale = Locale.getDefault();
    }
    if (zone == null) {
    
    
        zone = TimeZone.getDefault();
    }
    Calendar cal;
    if (type == null) {
    
    
        type = locale.getUnicodeLocaleType("ca");
    }
    if (type == null) {
    
    
        if (locale.getCountry() == "TH"
            && locale.getLanguage() == "th") {
    
    
            type = "buddhist";
        } else {
    
    
            type = "gregory";
        }
    }
    switch (type) {
    
    
    case "gregory":
        cal = new GregorianCalendar(zone, locale, true);
        break;
    case "iso8601":
        GregorianCalendar gcal = new GregorianCalendar(zone, locale, true);
        // make gcal a proleptic Gregorian
        gcal.setGregorianChange(new Date(Long.MIN_VALUE));
        // and week definition to be compatible with ISO 8601
        setWeekDefinition(MONDAY, 4);
        cal = gcal;
        break;
    case "buddhist":
        cal = new BuddhistCalendar(zone, locale);
        cal.clear();
        break;
    case "japanese":
        cal = new JapaneseImperialCalendar(zone, locale, true);
        break;
    default:
        throw new IllegalArgumentException("unknown calendar type: " + type);
    }
    cal.setLenient(lenient);
    if (firstDayOfWeek != 0) {
    
    
        cal.setFirstDayOfWeek(firstDayOfWeek);
        cal.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek);
    }
    if (isInstantSet()) {
    
    
        cal.setTimeInMillis(instant);
        cal.complete();
        return cal;
    }
    if (fields != null) {
    
    
        boolean weekDate = isSet(WEEK_YEAR)
                               && fields[WEEK_YEAR] > fields[YEAR];
        if (weekDate && !cal.isWeekDateSupported()) {
    
    
            throw new IllegalArgumentException("week date is unsupported by " + type);
        }
        // Set the fields from the min stamp to the max stamp so that
        // the fields resolution works in the Calendar.
        for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) {
    
    
            for (int index = 0; index <= maxFieldIndex; index++) {
    
    
                if (fields[index] == stamp) {
    
    
                    cal.set(index, fields[NFIELDS + index]);
                    break;
                }
            }
        }
        if (weekDate) {
    
    
            int weekOfYear = isSet(WEEK_OF_YEAR) ? fields[NFIELDS + WEEK_OF_YEAR] : 1;
            int dayOfWeek = isSet(DAY_OF_WEEK)
                            ? fields[NFIELDS + DAY_OF_WEEK] : cal.getFirstDayOfWeek();
            cal.setWeekDate(fields[NFIELDS + WEEK_YEAR], weekOfYear, dayOfWeek);
        }
        cal.complete();
    }
    return cal;
}

MyBatis

MyBatis中有很多构建对象的方式都使用到了建造者模式

比如缓存对象,这个对象的生成又包含了建造者模式,又包含了前面看到的装饰器模式。

public Cache useNewCache(Class<? extends Cache> typeClass,
      Class<? extends Cache> evictionClass,
      Long flushInterval,
      Integer size,
      boolean readWrite,
      boolean blocking,
      Properties props) {
    
    
    Cache cache = new CacheBuilder(currentNamespace)
        .implementation(valueOrDefault(typeClass, PerpetualCache.class))
        .addDecorator(valueOrDefault(evictionClass, LruCache.class))
        .clearInterval(flushInterval)
        .size(size)
        .readWrite(readWrite)
        .blocking(blocking)
        .properties(props)
        .build();
    configuration.addCache(cache);
    currentCache = cache;
    return cache;
  }

MappedStatement对象

  public MappedStatement addMappedStatement(
      String id,
      SqlSource sqlSource,
      StatementType statementType,
      SqlCommandType sqlCommandType,
      Integer fetchSize,
      Integer timeout,
      String parameterMap,
      Class<?> parameterType,
      String resultMap,
      Class<?> resultType,
      ResultSetType resultSetType,
      boolean flushCache,
      boolean useCache,
      boolean resultOrdered,
      KeyGenerator keyGenerator,
      String keyProperty,
      String keyColumn,
      String databaseId,
      LanguageDriver lang,
      String resultSets) {
    
    

    if (unresolvedCacheRef) {
    
    
      throw new IncompleteElementException("Cache-ref not yet resolved");
    }

    id = applyCurrentNamespace(id, false);
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;

    MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
        .resource(resource)
        .fetchSize(fetchSize)
        .timeout(timeout)
        .statementType(statementType)
        .keyGenerator(keyGenerator)
        .keyProperty(keyProperty)
        .keyColumn(keyColumn)
        .databaseId(databaseId)
        .lang(lang)
        .resultOrdered(resultOrdered)
        .resultSets(resultSets)
        .resultMaps(getStatementResultMaps(resultMap, resultType, id))
        .resultSetType(resultSetType)
        .flushCacheRequired(valueOrDefault(flushCache, !isSelect))
        .useCache(valueOrDefault(useCache, isSelect))
        .cache(currentCache);

    ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);
    if (statementParameterMap != null) {
    
    
      statementBuilder.parameterMap(statementParameterMap);
    }

    MappedStatement statement = statementBuilder.build();
    configuration.addMappedStatement(statement);
    return statement;
  }

Guava

看起来构建缓存对象非常适合使用建造者模式,在Guava中也和MyBatis一样,选择了建造者模式。

在这里插入图片描述

Guess you like

Origin blog.csdn.net/CSDN_WYL2016/article/details/121088248