一文读懂观察者模式
由于业务需求,我要实现一个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)
笔者第一篇文章,如有不完善的地方请多多指出~