1. 概述
享元设计模式(Flyweight Pattern):通过尽量共享实例来避免new出实例。
享元设计模式中有两个角色,一是要共享的实例,二是获取或创建这些共享实例的工厂。
举一个例子:例如 String 常量池,大家创建的String常量,创建String的时候,先去常量池中看一下,有该String常量直接使用该常量,如果没有就去创建,创建成功后放在常量池中,当然这些常量不允许修改的,享元模式中的共享的实例也不允许修改,一旦被修改,大家在共用的时候就会出现问题。
2. 享元设计模式在 FastDateFormat类中的应用
这里的FastDateFormat指的是 apache 工具包(org.apache.commons.lang3.time)里面的一个类。
FastDateFormat 类既充当工厂角色,也充当共享的对象,pool是一个Map,key 是 getInstance 方法的参数,value 是 FastDateFormat实例,参数是日期的格式,例:yyyy-MM-dd。
先看下 getInstance 方法,该方法第一步使用参数生成 key,使用 key 去获取 共享的 FastDateFormat 对象,无已经创建的 FastDateFormat 共享对象则创建。
public F getInstance(final String pattern, TimeZone timeZone, Locale locale) {
Validate.notNull(pattern, "pattern must not be null");
if (timeZone == null) {
timeZone = TimeZone.getDefault();
}
if (locale == null) {
locale = Locale.getDefault();
}
// 使用参数生成 key
final MultipartKey key = new MultipartKey(pattern, timeZone, locale);
// 使用 key 去获取 共享的 FastDateFormat 对象
F format = cInstanceCache.get(key);
// 无已经创建的 FastDateFormat 共享对象则创建
if (format == null) {
format = createInstance(pattern, timeZone, locale);
final F previousValue= cInstanceCache.putIfAbsent(key, format);
if (previousValue != null) {
// another thread snuck in and did the same work
// we should return the instance that is in ConcurrentMap
format= previousValue;
}
}
return format;
}
pool 如下所示
private final ConcurrentMap<MultipartKey, F> cInstanceCache = new ConcurrentHashMap<>(7);
key 如下所示, key 是使用 getInstance 方法参数通过计算(下面代码中的hashCode方法)得来:
private static class MultipartKey {
private final Object[] keys;
private int hashCode;
/**
* Constructs an instance of <code>MultipartKey</code> to hold the specified objects.
* @param keys the set of objects that make up the key. Each key may be null.
*/
MultipartKey(final Object... keys) {
this.keys = keys;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(final Object obj) {
// Eliminate the usual boilerplate because
// this inner static class is only used in a generic ConcurrentHashMap
// which will not compare against other Object types
return Arrays.equals(keys, ((MultipartKey)obj).keys);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
if(hashCode==0) {
int rc= 0;
for(final Object key : keys) {
if(key!=null) {
rc= rc*7 + key.hashCode();
}
}
hashCode= rc;
}
return hashCode;
}
}
参考文献
- 图解设计模式 结成浩
- 图解设计模式 尚硅谷