详解 - Builder模式

Android设计模式”这个系列主要是对Android项目中的设计模式进行分析总结,学习自《Android 源码设计模式解析与实战》,错误之处烦请指正~


Android设计模式系列文章:

1、详解 - 单例模式
2、详解 - Builder模式


一、 概述

1.1 定义

将一个复杂对象的构建与表示分离开来,使得同样的构建过程可以创建不同的表示。

1.2 使用场景

  • 相同的方法,不同的执行顺序,产生不同的结果

  • 多中属性都可以装配到一个对象中,但是产生的运行结果不同

  • 复杂的产品类,或者产品类结果会随调用顺序发生改变

  • 初始化一个对象特别复杂,如参数特别多,且很多参数都具有默认值时

1.3 分析

Builder模式将部件和组装过程分离,使得构建过程和部件都可以自由扩展,从而降低两者耦合度。

优点:

  • 良好的封装性,使用Builder模式可以使客户端不必知道产品内部的组成细节
  • Builder独立,易于扩展

缺点:

  • 会产生冗余的Builder对象以及组装对象,消耗内存

二、 实现

2.1 示例

Builder模式非常易于上手,我们通过分析一个简单的demo来感受Builder模式的魅力。

EventBus 框架中的 EventBusBuilder 就采用 Builder 模式实现,我们来分析Builder模式的实现,EventBus 3.0 源码解析见 EventBus3.源码解析。

EventBusBuilderEventBus 框架中的个性化配置类,从类名就可以看出这是一个 Builder 模式,通过Builder 对象来组装个性化设置 EventBus 的各项参数配置,包括 是否通过Log输出异常信息logSubscriberExceptions 等。下面看看 EventBusBuilder 的相关源码。

public class EventBusBuilder {
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

    boolean logSubscriberExceptions = true;//是否通过Log输出异常信息
    boolean logNoSubscriberMessages = true;//是否通过Log输出发送事件无订阅者信息
    boolean sendSubscriberExceptionEvent = true;//是否将内部异常信息通过SubscriberExceptionEvent发送出去
    boolean sendNoSubscriberEvent = true;//是否将无订阅者的时间通过NoSubscriberEvent发送出去
    boolean throwSubscriberException;//是否将内部异常信息通过EventBusException抛出
    boolean eventInheritance = true;//发送事件是否支持调用所有父类及实现的接口
    boolean ignoreGeneratedIndex;//是否忽略生成被观察者订阅的方法(通过反射)
    boolean strictMethodVerification;//是否开启严格的方法验证,(public,只有一个参数,不为static及abstract),非法则均抛出异常
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;//发送事件的线程池
    List> skipMethodVerificationForClasses;//对类忽略方法校验,目前未实现
    List subscriberInfoIndexes;//通过annotation preprocessor生成的订阅者方法list

    EventBusBuilder() {
    }

    /**
     * 设置 logSubscriberExceptions,默认为true
     * @param logSubscriberExceptions
     * @return
     */
    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
        this.logSubscriberExceptions = logSubscriberExceptions;
        return this;
    }

    /**
     * 设置 logNoSubscriberMessages,默认为 true
     * @param logNoSubscriberMessages
     * @return
     */
    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
        this.logNoSubscriberMessages = logNoSubscriberMessages;
        return this;
    }

    /**
     * 设置 sendSubscriberExceptionEvent,默认为 true
     * @param sendSubscriberExceptionEvent
     * @return
     */
    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
        return this;
    }

    /**
     * 设置 sendNoSubscriberEvent,默认为 true
     * @param sendNoSubscriberEvent
     * @return
     */
    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
        this.sendNoSubscriberEvent = sendNoSubscriberEvent;
        return this;
    }

    /**
     * 设置 throwSubscriberException,默认为 false
     * @param throwSubscriberException
     * @return
     */
    public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
        this.throwSubscriberException = throwSubscriberException;
        return this;
    }

    /**
     * 设置 eventInheritance,默认为 true
     * @param eventInheritance
     * @return
     */
    public EventBusBuilder eventInheritance(boolean eventInheritance) {
        this.eventInheritance = eventInheritance;
        return this;
    }


    /**
     * 设置 executorService
     * @param executorService
     * @return
     */
    public EventBusBuilder executorService(ExecutorService executorService) {
        this.executorService = executorService;
        return this;
    }

    /**
     * 设置 skipMethodVerificationForClasses
     * @param clazz
     * @return
     */
    public EventBusBuilder skipMethodVerificationFor(Class clazz) {
        if (skipMethodVerificationForClasses == null) {
            skipMethodVerificationForClasses = new ArrayList<>();
        }
        skipMethodVerificationForClasses.add(clazz);
        return this;
    }

    /**
     * 设置 ignoreGeneratedIndex
     * @param ignoreGeneratedIndex
     * @return
     */
    public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
        return this;
    }

    /**
     * 设置 strictMethodVerification
     * @param strictMethodVerification
     * @return
     */
    public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
        this.strictMethodVerification = strictMethodVerification;
        return this;
    }

    /**
     * 设置 subscriberInfoIndexes
     * @param index
     * @return
     */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if(subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

    /**
     * 实现修改 EventBus 默认 EventBusBuilder(EventBus.defaultInstance)
     * @return
     */
    public EventBus installDefaultEventBus() {
        synchronized (EventBus.class) {
            if (EventBus.defaultInstance != null) {
                throw new EventBusException("Default instance already exists." +
                        " It may be only set once before it's used the first time to ensure consistent behavior.");
            }
            EventBus.defaultInstance = build();
            return EventBus.defaultInstance;
        }
    }

    /**
     * 通过 build 方式实现 EventBus 初始化
     * @return
     */
    public EventBus build() {
        return new EventBus(this);
    }

}

上述代码中,EventBusBuilder 类可以设置 EventBus 中的 * logSubscriberExceptions、logNoSubscriberMessages、sendSubscriberExceptionEvent* 等参数,这些参数统一存储在 EventBusBuilder 中。在调用 EventBusBuilder 类的 build() 函数时会创建 EventBus,并且将各项配置用于到 EventBus 中去。

EventBusBuilder 采用 Builder 模式主要是初始化 EventBus 配置项参数复杂,并且很多参数具有默认值,在使用时可能只需要对部分参数进行修改,故采用 Builder 模式方便修改初始化。

2.2 小结

通过 2.1节 可以看出 Builder 模式使用非常方便,并且对于多参数属性初始化来说,极大的简化了工作。

在项目中合理的加入 Builder 模式吧~

三、小结

Builder 模式在 Android 开发中较为常用,通常作为配置类的构造器将配置的构建和表示分离开来,同时也实现了将配置类从目标类中抽离出来,避免了过多的 setter 方法。

Builder 模式比较常见的实现方式是通过调用链实现,这样使得代码简单易懂。


本文对 Builder模式 的分析到此就结束了,部分内容学习自 《Android源码设计模式 解析与实战》

附:

EventBus3(3.0.0)源码解析

你可能感兴趣的:(详解 - Builder模式)