Builder模式用於建立複雜物件
阿新 • • 發佈:2018-12-10
這種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();