我的理解:就是构造函数的时候,可以灵活的设置它的值,如果构造函数很多的值,不用全部传,需要什么值,就放什么值,封装了set方法一样,一步一步构造自己想要的属性
它的意思就是将一个对象和怎么构建这个对象分离开来,如果你想构建一个对象,你把这个消息告诉构建者,并且将自己对这个对象的各种要求告诉建造者,然后建造者根据这 些要求进行捣鼓,然后,你所需要的一个对象就出来了。
BUILDER—MM最爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM也可以轻松搞定,这就是我的“我爱你 ”builder。(这一定比美军在伊拉克用的翻译机好卖)
建造模式:将对象的内部表象和对象的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
本来呢,我们根据Builder接口实现不同的具体的ConcreteBuilder,就可生产不同的对象了。
但是,下面例子的只有一个Builder,所以也没有接口Builder,也没有其他的ConcreteBuilder。
但是我今天要讲的例子太简单,简单到都不觉得是建造者模式,但是又有建造者模式的感觉。
建造者模式:AlertDialog.Builder
简介:可以分步地构造每一部分。
AlertDialog里面有一个静态类builder,里面封装什么设置按钮的文字的
public static class Builder { private final AlertController.AlertParams P; /** * Creates a builder for an alert dialog that uses the default alert * dialog theme. * <p> * The default alert dialog theme is defined by * {@link android.R.attr#alertDialogTheme} within the parent * {@code context}'s theme. * * @param context the parent context */ public Builder(Context context) { this(context, resolveDialogTheme(context, 0)); }
public class AlertDialog extends Dialog implements DialogInterface { private AlertController mAlert; /** * Hint layout to the side. * @hide */ public static final int LAYOUT_HINT_SIDE = 1; /** * Creates an alert dialog that uses the default alert dialog theme. * <p> * The default alert dialog theme is defined by * {@link android.R.attr#alertDialogTheme} within the parent * {@code context}'s theme. * * @param context the parent context * @see android.R.styleable#Theme_alertDialogTheme */ protected AlertDialog(Context context) { this(context, 0); } /** * Creates an alert dialog that uses the default alert dialog theme and a * custom cancel listener. * <p> * This is functionally identical to: * <pre> * AlertDialog dialog = new AlertDialog(context); * alertDialog.setCancelable(cancelable); * alertDialog.setOnCancelListener(cancelListener); * </pre> * <p> * The default alert dialog theme is defined by * {@link android.R.attr#alertDialogTheme} within the parent * {@code context}'s theme. * * @param context the parent context * @see android.R.styleable#Theme_alertDialogTheme */ protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { this(context, 0); setCancelable(cancelable); setOnCancelListener(cancelListener); } /** * Gets the list view used in the dialog. * * @return The {@link ListView} from the dialog. */ public ListView getListView() { return mAlert.getListView(); } @Override public void setTitle(CharSequence title) { super.setTitle(title); mAlert.setTitle(title); } /** * Set resId to 0 if you don't want an icon. * @param resId the resourceId of the drawable to use as the icon or 0 * if you don't want an icon. */ public void setIcon(@DrawableRes int resId) { mAlert.setIcon(resId); } public void setIcon(Drawable icon) { mAlert.setIcon(icon); } public static class Builder { private final AlertController.AlertParams P; /** * Creates a builder for an alert dialog that uses the default alert * dialog theme. * <p> * The default alert dialog theme is defined by * {@link android.R.attr#alertDialogTheme} within the parent * {@code context}'s theme. * * @param context the parent context */ public Builder(Context context) { this(context, resolveDialogTheme(context, 0)); } /** * Creates a builder for an alert dialog that uses an explicit theme * resource. * <p> * The specified theme resource ({@code themeResId}) is applied on top * of the parent {@code context}'s theme. It may be specified as a * style resource containing a fully-populated theme, such as * {@link android.R.style#Theme_Material_Dialog}, to replace all * attributes in the parent {@code context}'s theme including primary * and accent colors. * <p> * To preserve attributes such as primary and accent colors, the * {@code themeResId} may instead be specified as an overlay theme such * as {@link android.R.style#ThemeOverlay_Material_Dialog}. This will * override only the window attributes necessary to style the alert * window as a dialog. * <p> * Alternatively, the {@code themeResId} may be specified as {@code 0} * to use the parent {@code context}'s resolved value for * {@link android.R.attr#alertDialogTheme}. * * @param context the parent context * @param themeResId the resource ID of the theme against which to inflate * this dialog, or {@code 0} to use the parent * {@code context}'s default alert dialog theme */ public Builder(Context context, int themeResId) { P = new AlertController.AlertParams(new ContextThemeWrapper( context, resolveDialogTheme(context, themeResId))); } /** * Returns a {@link Context} with the appropriate theme for dialogs created by this Builder. * Applications should use this Context for obtaining LayoutInflaters for inflating views * that will be used in the resulting dialogs, as it will cause views to be inflated with * the correct theme. * * @return A Context for built Dialogs. */ public Context getContext() { return P.mContext; } /** * Set the title using the given resource id. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setTitle(@StringRes int titleId) { P.mTitle = P.mContext.getText(titleId); return this; }
简单说就是把自个儿构造函数变成了保护类型,就不能主动创建了。那么创建需要一个使用它内部类Builder
ImageLoader的源码也用了构造者模式
public final class ImageLoaderUtil { // ImageLoader初始化 static { File cacheDir = StorageUtils.getOwnCacheDirectory(CXApplication.mAppContext, "imgCache"); FileNameGenerator fileNameGenerator = new Md5FileNameGenerator();// UnlimitedDiskCache diskCache = new UnlimitedDiskCache(cacheDir, null, fileNameGenerator); UsingFreqLimitedMemoryCache memoryCache = new UsingFreqLimitedMemoryCache((int) (Runtime.getRuntime().maxMemory() / 16));// 缓存内存大小 DisplayImageOptions displayImageOptions = new DisplayImageOptions .Builder() .cacheOnDisk(true)/* 磁盘缓存 */ .cacheInMemory(true) /* 内存缓存 */ .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2).bitmapConfig(Bitmap.Config.RGB_565) .showImageOnLoading(R.drawable.j_iv_loading)// 加载过程图片 .showImageOnFail(R.drawable.j_iv_loading_fail_large)// 失败图片 .build(); ImageLoaderConfiguration imageLoaderConfiguration = new ImageLoaderConfiguration .Builder(CXApplication.mAppContext) .diskCache(diskCache) .memoryCache(memoryCache) .defaultDisplayImageOptions(displayImageOptions) .denyCacheImageMultipleSizesInMemory() .threadPoolSize(4)// 线程池内加载的数量 .tasksProcessingOrder(QueueProcessingType.FIFO)// 先进先出 .memoryCacheExtraOptions(CXLocConfig.ScreenWidthPixels, CXLocConfig.ScreenHeightPixels)// 最大内存缓存图片宽高 .diskCacheFileCount(100)// 磁盘最多缓存100张图片 .diskCacheSize(50 * 1024 * 1024)// 磁盘最大缓存50M的图片 .memoryCache(new WeakMemoryCache()) .memoryCacheSizePercentage(15) .build(); ImageLoader.getInstance().init(imageLoaderConfiguration);// 全局初始化此配置 }
public final class DisplayImageOptions { private final int imageResOnLoading; private final int imageResForEmptyUri; private final int imageResOnFail; private final Drawable imageOnLoading; private final Drawable imageForEmptyUri; private final Drawable imageOnFail; private final boolean resetViewBeforeLoading; private final boolean cacheInMemory; private final boolean cacheOnDisk; private final ImageScaleType imageScaleType; private final Options decodingOptions; private final int delayBeforeLoading; private final boolean considerExifParams; private final Object extraForDownloader; private final BitmapProcessor preProcessor; private final BitmapProcessor postProcessor; private final BitmapDisplayer displayer; private final Handler handler; private final boolean isSyncLoading; private DisplayImageOptions(DisplayImageOptions.Builder builder) { this.imageResOnLoading = builder.imageResOnLoading; this.imageResForEmptyUri = builder.imageResForEmptyUri; this.imageResOnFail = builder.imageResOnFail; this.imageOnLoading = builder.imageOnLoading; this.imageForEmptyUri = builder.imageForEmptyUri; this.imageOnFail = builder.imageOnFail; this.resetViewBeforeLoading = builder.resetViewBeforeLoading; this.cacheInMemory = builder.cacheInMemory; this.cacheOnDisk = builder.cacheOnDisk; this.imageScaleType = builder.imageScaleType; this.decodingOptions = builder.decodingOptions; this.delayBeforeLoading = builder.delayBeforeLoading; this.considerExifParams = builder.considerExifParams; this.extraForDownloader = builder.extraForDownloader; this.preProcessor = builder.preProcessor; this.postProcessor = builder.postProcessor; this.displayer = builder.displayer; this.handler = builder.handler; this.isSyncLoading = builder.isSyncLoading; } public boolean shouldShowImageOnLoading() { return this.imageOnLoading != null || this.imageResOnLoading != 0; } public boolean shouldShowImageForEmptyUri() { return this.imageForEmptyUri != null || this.imageResForEmptyUri != 0; } public boolean shouldShowImageOnFail() { return this.imageOnFail != null || this.imageResOnFail != 0; } boolean isSyncLoading() { return this.isSyncLoading; } public static DisplayImageOptions createSimple() { return (new DisplayImageOptions.Builder()).build(); } public static class Builder {
如Gson中的GsonBuilder,代码太长了,就不贴了,有兴趣自己去看源码,这里只贴出其Builder的使用方法。
GsonBuilder builder=new GsonBuilder();
Gson gson=builder.setPrettyPrinting()
.disableHtmlEscaping()
.generateNonExecutableJson()
.serializeNulls()
.create();
EventBus中也有一个Builder,只不过这个Builder外部访问不到而已,因为它的构造函数不是public的,但是你可以在EventBus这个类中看到他的应用
public static EventBusBuilder builder() {
return new EventBusBuilder();
}
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
subscriptionsByEventType = new HashMap<Class<?>, CopyOnWriteArrayList<Subscription>>();
typesBySubscriber = new HashMap<Object, List<Class<?>>>();
stickyEvents = new ConcurrentHashMap<Class<?>, Object>();
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
subscriberMethodFinder = new SubscriberMethodFinder(builder.skipMethodVerificationForClasses);
logSubscriberExceptions = builder.logSubscriberExceptions;
logNoSubscriberMessages = builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
throwSubscriberException = builder.throwSubscriberException;
eventInheritance = builder.eventInheritance;
executorService = builder.executorService;
}
网络请求框架OkHttp
private Response(Builder builder) {
this.request = builder.request;
this.protocol = builder.protocol;
this.code = builder.code;
this.message = builder.message;
this.handshake = builder.handshake;
this.headers = builder.headers.build();
this.body = builder.body;
this.networkResponse = builder.networkResponse;
this.cacheResponse = builder.cacheResponse;
this.priorResponse = builder.priorResponse;
}
参考博客:
https://my.oschina.net/weiCloudS/blog/392872
http://blog.csdn.net/fofu33/article/details/50973172