这种Builder模式使用静态内部类实现。当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时,使用这种模式可以使创建对象的过程更清晰。
比如有一个Request类,代表请求,这个请求有很多属性。
public final class Request {
private static final long TOO_LONG_LOG = TimeUnit.SECONDS.toNanos(5);
private static final int KEY_PADDING = 50; // Determined by exact science.
static final char KEY_SEPARATOR = '\n';
int id;
/** The time that the request was first submitted (in nanos). */
long started;
/**
* uri和resourceId是互斥的
*/
@Nullable
public final Uri uri;
/**
* resourceId和uir是互斥的
*/
public final int resourceId;
@Nullable
public final Bitmap.Config config;
/**
* 缓存key
*/
@Nullable
public final String key;
/**
* 可选的可以替代uri和resourceId的稳定key
*/
@Nullable
public final String stableKey;
/**
* 用户追踪的tag
*/
@Nullable
public final Object tag;
Request(Builder builder){
this.config = builder.config;
this.resourceId = builder.resourceId;
this.uri = builder.uri;
this.tag = builder.tag;
this.stableKey = builder.stableKey;
if (Looper.myLooper() == Looper.getMainLooper()){
this.key = createKey();
}else {
this.key = createKey(new StringBuilder());
}
}
private String createKey(){
String result = createKey(MAIN_THREAD_KEY_BUILDER);
MAIN_THREAD_KEY_BUILDER.setLength(0);
return result;
}
private String createKey(StringBuilder sb){
Request data = this;
if (data.stableKey != null){
sb.ensureCapacity(data.stableKey.length() + KEY_PADDING);
sb.append(data.stableKey);
}else if (data.uri != null){
String path = data.uri.toString();
sb.ensureCapacity(path.length() + KEY_PADDING);
sb.append(path);
}else {
sb.ensureCapacity(KEY_PADDING);
sb.append(data.resourceId);
}
sb.append(KEY_SEPARATOR);
return sb.toString();
}
String logId(){
long delta = System.nanoTime() - started;
if (delta > TOO_LONG_LOG){
return plainId() + "+" + TimeUnit.NANOSECONDS.toSeconds(delta) + "s";
}
return plainId() + "+" + TimeUnit.NANOSECONDS.toNanos(delta) + "ms";
}
String plainId() {
return "[R" + id + "]";
}
String getName() {
if (uri != null){
return String.valueOf(uri.getPath());
}
return Integer.toHexString(resourceId);
}
/**
* builder for creating {@link Request}
*/
public static final class Builder {
@Nullable Uri uri;
int resourceId;
@Nullable String key;
@Nullable Bitmap.Config config;
@Nullable Object tag;
@Nullable String stableKey;
public Builder (@NonNull Uri uri){
setUri(uri);
}
public Builder(@DrawableRes int resourceId){
setResourceId(resourceId);
}
Builder(@Nullable Uri uri,int resourceId, @Nullable Bitmap.Config bitmapConfig){
this.uri = uri;
this.resourceId = resourceId;
this.config = bitmapConfig;
}
Builder(Request request){
uri = request.uri;
resourceId = request.resourceId;
stableKey = request.stableKey;
config = request.config;
}
/**
* 设置uri,并且重置id
* @param uri
* @return
*/
@NonNull
public Builder setUri(@NonNull Uri uri) {
if (uri == null){
throw new IllegalArgumentException("Image uri may not be null.");
}
this.uri = uri;
this.resourceId = 0;
return this;
}
@NonNull
public Builder stableKey(@Nullable String stableKey) {
this.stableKey = stableKey;
return this;
}
/**
* 设置Id,并且重置uri
* @param resourceId
* @return
*/
@NonNull
public Builder setResourceId(int resourceId){
if (resourceId == 0){
throw new IllegalArgumentException("Image resourceId may not be 0");
}
this.resourceId = resourceId;
this.uri = null;
return this;
}
@NonNull
public Builder tag(@NonNull Object tag){
if (tag == null){
throw new IllegalArgumentException("tag may not be null");
}
if (this.tag != null){
throw new IllegalStateException("tag already set");
}
this.tag = tag;
return this;
}
Builder clearTag(){
this.tag = null;
return this;
}
@Nullable
Object getTag(){
return tag;
}
@NonNull
public Builder config(@NonNull Bitmap.Config config){
checkNotNull(config,"config 是 null");
this.config = config;
return this;
}
public Request build(){
return new Request(this);
}
}
}
代码来自Picasso源码,
这样我们调用这个请求就可以:
Request request = new Request.Builder(R.drawable.actionbar_shadow_up).stableKey("1123").build();