注:所述内容,只描述必要部分或者重点,以便于您有个宏观了解。关键字,类型描述,命名等细节,不必深究,可参考其他文章。
1.什么是观察者模式
开门见山,首先什么是观察者模式,核心概念就是:观察者(Observer)和可观察对象(Observable),可观察对象是一个源,异步的发出一些值。其次观察者,订阅这个源,并对发出的值做全响应或部分响应。
两者是**一对多**的关系:可观察对象(1)==>观察者(n)
举例:
step_1:你订阅了《读者》,向读者杂志社发了一个
订单 = {addr:xxxx, 订单id:9527, 行为:寄到家}。
step_2: 我订阅了《读者》,向读者杂志社发了一个
订单 = {addr:email, 订单id:1314, 行为:电子版到邮箱}。
step_3: 读者杂志社,有一个订单列表。然后不定时发布杂志,每次发布遍历订单表,根据addr和 行为 做响应的操作。
2.常见实现方式
上述内容,一种实现方式就是(伪代码):
class Observable{
订单list = [];
add(){ list.push()};
remove(){ list.remove};
notifyAll(newBook){ list.forEach()}; //通知列表中所有订单的用户,有新杂质,并调用订单中行为函数
}
Interface Observer{
update(){ // 订单中的行为
//你和我两个人的接受新杂志的方式不一样
}
}
//生成一个订单
let me = new Observer('我','hex@qq.com')
me.update = ()=>{ //给我发电子版到邮箱}
observable.add(me)
3.那么angular中的观者模式是什么样的?
同样两个对象,可观察对象和观察者。原理大致相同:观察者通过可观察对象的订阅方法进行订阅,可观察对象有了新值后,调用观察者的某个方法通知观察者。
先说Observer(观察者),这个类型描述如下:
Interface Observer{
next(){} // 有新《读者》发布了:拿到书你会执行读书的操作
error(){} // 杂志社倒闭了:你得想着是退钱,还是再定其他的杂志
complete(){} // 通知你:你交了一年的钱,已经给你推了12个月,再不给你推了
}
接下来,说Observable(可观察对象)
Class Obsevable{
fn: Function; // (Observer) => { unSubscribe: () => {} }
constructor(fn){
this.fn = fn;
}
subscribe(observer){
this.fn(observer);
}
}
可观察对象的主要结构大致如此。细说就是:
subscribe: 订阅函数,接受一个 Observer对象
如上所述:Observer这个样子:
{
next(){},
error(){},
complete(){}
};
然后把这个observer当做fn的参数,去调用 fn;
怎么实例化这个Observable呢?那就需要一个fn类型的参数,fn 是什么样子?
这个样子,主要是三部分,中文社区称之为subscriber function(订阅者函数):
读者_Fn = (observer) => {
// 1- 从observer中拿到回调方法
const {next, error , complete} = observer;
// 2- 然后发起一个异步请求
// 比如持续订阅《读者》一年,跟先前定义Observer的内容比较
// 当新读者发布了,调用next()
// 一年的都给你推完了, 调用 complete()
// 3- 最后要返回一个取消订阅的方法:有新的《读者》也不要给你发了
return unSubscribe = () => {}
}
最后实例化一个Observable:
读者_Observable = new Observable(读者_Fn);
我去订阅《读者》就是:
subscription = 读者_Observable.subscribe(my_observer_instance);
// subscription : { unSubscribe()=>{} }
总结
要使用angular中的观察者模式完成一次订阅一年《读者》的任务。分为4步:
step_1: 建立一个观察者函数,观察者函数的职能是,
接收一个Observer对象
发起获取《读者》的请求,并在读者杂志社 返回新消息的时候,添加回调
返回,一个取消杂志订阅的函数
step_2: 用 Step_1的观察者函数,实例化一个 《读者》的发布源,
step_3: 因为每个观察者,的next、error处理方式是自己独特的。你订阅是为了看纸质版,
我订阅是为了糊墙,即每个观察者的next不尽相同。
所以,实例几个观察者,你自己的,小明的,李磊等等的 observer对象
step_4: 通过《读者》的发布源的 subscribe方法,让上面几个人物都订阅《读者》