一周两个设计模式—观察者模式(第六周)
业务场景:
自从小犬帮助天庭咖啡馆解决了咖啡师分配订单的问题顺利被评为了年度优秀人物之后,玉兔对它的态度都好了很多,都主动联系它了,并且
天王的干女儿白毛老鼠也时不时的对其示好,这日子过得简直不要太舒服,但是今天天王又来电话了,原来是之前咖啡厅扩展了外卖业务,
当然了系统也是外包的,外包给巨灵神了,试运行了几天发现了一些问题,例如顾客下的订单不能及时通知后台,设备运行时间过长经常
出现卡机的现象,这一看巨灵神解决不了,直接找到小犬了(顾客投诉太多了,天王顶不住了)。
没办法,得维护关系不是,于是小犬急忙骑着筋斗云(大圣最新产品)到了咖啡馆的机房,看代码呗,卧槽,什么鬼,获取订单居然在每个
界面都使用了一个定时循环Timer,每隔5Min轮询一次接口,真是人才,这样能及时才怪呢,最长能到五分钟才能接单,并且,如果没有
新订单就是空跑,浪费资源,人才啊。
分析问题:
这次的问题其实很简单,就是及时,就是说当有新订单到来的时候需要第一时间通知到,而不是需要做一个定时的查看、访问有没有新消
息,这么一说是不是有点明白,像不像广播,一次发送,在想要处理的地方接收就可以了并且如果没有新的订单,这里是不执行任何操作
的,这么一说,查一下设计模式的类型,就见一个明晃晃的名字告诉你-观察者模式,快来用它。
定义:
发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有
依赖于它的对象都会得到通知并自动更新。
结构:
被观察者:数据源发生变化并且通知更新
观察者:接收变化的数据
解决的问题:
一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
优点:
观察者和被观察者是抽象耦合的
建立了一套触发机制
缺点:
如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
如果观察者和观察目标间有循环依赖,可能导致系统崩溃
没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的
注意事项:
避免循环引用
如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式
知道用什么方式了,那接下来就是实现的问题了,大家请看代码。
//被观察者的抽象
interface CoffeeOrder {
fun receiveOrder(order:String)
}
//被观察者的实际功能
class FirstOrder(var name:String):CoffeeOrder {
override fun receiveOrder(order: String) {
Log.v("=========","$name====$order")
}
}
//观察者管理
interface Send {
fun addOrder(coffeeOrder: CoffeeOrder)
fun removeOrder(coffeeOrder: CoffeeOrder)
fun notifyOrder(order:String)
}
//观察者管理具体实现,其实可以使用单例模式来维护,否则会有重复的可能性导致注册两次
class SendOrder:Send {
var sendOrders:MutableList<CoffeeOrder> = mutableListOf() //可以使用Map
override fun addOrder(coffeeOrder: CoffeeOrder) {
sendOrders.add(coffeeOrder) //添加之前需要判断是否有重复的
}
override fun removeOrder(coffeeOrder: CoffeeOrder) {
if(!sendOrders.isNullOrEmpty()){
sendOrders.remove(coffeeOrder)
}
}
override fun notifyOrder(order: String) {
sendOrders.forEach {
it.receiveOrder(order)
}
}
}
总结:
观察者算是开发者用的比较多的开发模式了,其实就是订阅-》分发,在数据源发生改变的时候进行分发这就是被订阅者,而订阅者通过
注册的方式进行监听,代码里大家也看到了消息的分发是依赖于一个循环语句,数量少的话还好,如果数量较多全部通知到会花费很长
的时间,及时也就是相对而不是绝对的,再有就是观察者接收到的只是一个结果,一个处理完的结果是比较封闭的,另外,所有的观察者
都是通过注册和解注册的方式实现的,需要手动维护注册和解注册的方式。
- 点赞
- 收藏
- 关注作者
评论(0)