EventBus源码分析​(四):EventBus中的几种设计模式

Quibbler 2021-10-13 900

EventBus源码分析(四):EventBus中的几种设计模式


        再看一下EventBus,总结一下其中几个重要的设计模式,也是最常见的几种设计模式:单例模式建造者模式观察者模式。多看源码的好处之一就是能从优秀的代码里活学活用。



1、单例模式

        单例模式(Singleton Pattern)是设计模式中最简单也是最常见的设计模式。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。


        通常用一个私有静态变量存储这个唯一的实例,而且有的源码中还会加上volatile关键字修饰:

    static volatile EventBus defaultInstance;

        类提供了一种访问其唯一的对象的方式,可以直接访问类的实例,不需要再实例化该类的对象。这个方法也是实现单例模式的关键,EventBus中提供getDefault()方法获取全局唯一的EventBus单例,这种单例使用的是双检锁(DCL)方式,实现单例模式的方法参考单例的五种方式一文。

    /** Convenience singleton for apps using a process-wide EventBus instance. */
    public static EventBus getDefault() {
        EventBus instance = defaultInstance;
        if (instance == null) {
            synchronized (EventBus.class) {
                instance = EventBus.defaultInstance;
                if (instance == null) {
                    instance = EventBus.defaultInstance = new EventBus();
                }
            }
        }
        return instance;
    }

        有了getDefault()方法,开发者就可以随处随地的获取EventBus实例,进行发送事件、注册订阅者等操作。

    EventBus.getDefault().postSticky(new MessageEvent("Hello EventBus"));

        而Kotlin提供了更加方便的单例实现,使用object关键词创建实例,见《对象声明:object》一文。



2、建造者模式

        建造者模式(Builder Pattern)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。一个Builder类会一步一步构造最终的对象。该Builder类是独立于其他对象的。


        构造EventBus实例就用到了建造者模式,构造EventBus实例的构造方法用到了EventBusBuilder这个构造类。

    EventBus(EventBusBuilder builder) {
        logger = builder.getLogger();
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        ...
    }

        借助EventBusBuilder类构造配置信息,提供一系列的设置方法。而且这些方法返回建造者自身,可以方便的实现链式调用,对构造对象进行设置的方法调用一气呵成。

    /** Default: true */
    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
        this.logSubscriberExceptions = logSubscriberExceptions;
        return this;
    }
    
    /** Default: true */
    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
        this.logNoSubscriberMessages = logNoSubscriberMessages;
        return this;
    }
    
    /** Default: true */
    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
        return this;
    }
    
    /** Default: true */
    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
        this.sendNoSubscriberEvent = sendNoSubscriberEvent;
        return this;
    }
    ...

        建造者Builder类通常还会提供一个build()方法,当一切都设置完成,调用该方法生成最终的对象实例。如EventBusBuilder中的build()方法:

    /** Builds an EventBus based on the current configuration. */
    public EventBus build() {
        return new EventBus(this);
    }

        还可以用EventBusBuilder中的installDefaultEventBus()方法先初始化EventBus库默认的实例:

    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;
        }
    }

      借助EventBus中的EventBusBuilder建造者,开发者可以自行定义EventBus行为属性,详见EventBus源码分析(一):构造及订阅一文第1.3节



3、观察者模式

        观察者模式(Observer Pattern)定义了一种一对多的依赖关系,让多个观察者对象同时监听某一对象。当被观察的对象发生修改时,会自动通知所有观察它的对象。观察者模式属于行为型模式。此设计模式最重要的作用就是解耦!将观察者与被观察者解耦,使得它们之间的依赖性更小。


        EventBus就是使用了观察者模式,使代码间相互解耦。当发出消息时,通知所有注册的观察者(订阅者)。注册的订阅对象,其实就是观察者。

    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

       新的事件发送,就通知所有的观察者:

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        ...
        subscriptions = subscriptionsByEventType.get(eventClass);
        for (Subscription subscription : subscriptions) {
            ...
            postToSubscription(subscription, event, postingState.isMainThread);
            ...
        }
    }

        核心关系维护在两个Map映射中:subscriptionsByEventTypetypesBySubscriber,详见EventBus源码分析(一):构造及订阅一文第2.1节



        设计模式不是纸上谈兵,曾看过几本关于设计模式的书:《设计模式之禅》、《Head First设计模式》、《大话设计模式》、《Android源码设计模式》等,最大的体会是设计模式属于经验之谈,是前人对于编程的一套经验总结,几十种设计模式硬背倒不难,但要灵活运用,唯手熟尔。



相关博客:

        设计模式的六大原则和23种设计模式

        单例的五种方式

        

不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com