Android 最常用的设计模式五 安卓源码分析——建造者模式


我的理解:就是构造函数的时候,可以灵活的设置它的值,如果构造函数很多的值,不用全部传,需要什么值,就放什么值,封装了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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值