观察者模式的实战--IM消息接收

381 阅读1分钟

一文读懂观察者模式

由于业务需求,我要实现一个IM消息模块,那么面临一个设计上的问题,如何才能优雅的实现让不同module监听各种消息的接收嘞?

观察者模式

简单来说,我想要不同的模块去监听它自身的消息接收

话不多说,上代码

我需要封装一个简单的单例,用于注册消息的监听,注销消息的监听以及推送消息

(本文采用Kotlin哦)

单例

 object MsgReceiveService {}

首先需要一个容器,首选HashMap,key用来记录不同模块的id,value为listener的具体行为

 private var listenerMap: ConcurrentHashMap<AppId, CopyOnWriteArrayList<CommonMsgListener>> = ConcurrentHashMap()

由于HashMap、ArrayList是线程不安全的,容易引发异常,笔者比较倾向于采用ConcurrentHashMap以及CopyOnWriteArrayList(虽然在性能上有所欠缺,稳定才是王道)

下面呈上注册代码:

@JvmStatic
 fun register(appId: AppId, listener: CommonMsgListener) {
    if (listenerMap.containsKey(appId)) {
        if (listenerMap[appId]?.contains(listener) == true) {
            return
        }
        listenerMap[appId]?.add(listener)
    } else {
        listenerMap[appId] = CopyOnWriteArrayList(arrayListOf(listener))
    }
}

注销代码:

@JvmStatic
fun unregister(appId: AppId, listener: CommonMsgListener) {
    synchronized(listenerMap) {
        if (listenerMap.containsKey(appId)) {
            listenerMap[appId]?.remove(listener)
            if (listenerMap[appId]?.size == 0) {
                listenerMap.remove(appId)
            }
        }
    }
}

推送代码:

@JvmStatic
fun trigger(appId: Short, msg: IMMessage) {
    val id = AppId.findByValue(appId.toInt())
    if (id != null) {
        if (listenerMap.containsKey(id)) {
            val appListener: MutableList<CommonMsgListener>? = listenerMap[id]
            if (appListener != null) {
                for (listener: CommonMsgListener in appListener) {
                    listener.onReceive(msg)
                }
                LogBaseUtil.i("MsgReceiveService-> appId $appId Message $msg")
            }
        }
    }
}

封装进对外调用方法中

object IMSDK {
    fun registerMsgReceiveListener(appId: AppId, listener: CommonMsgListener) {
        MsgReceiveService.register(appId, listener)
    }

    fun unregisterMsgReceiveListener(appId: AppId, listener: CommonMsgListener) {
        MsgReceiveService.unregister(appId, listener)
    }
}

调用方式

注册:
IMSDK.registerMsgReceiveListener(AppId.AppMeeting, CommonMsgListener { msg ->
    //msg为收到的具体消息内容
})

注销:
IMSDK.unregisterMsgReceiveListener(AppId.AppMarket, msgListener)

推送:
MsgReceiveService.trigger(msg.appid, msg)

笔者第一篇文章,如有不完善的地方请多多指出~