一、原理图
二、观察者模式
1、手动触发的观察者模式
/*
* @Author: laifeipeng
* @Date: 2019-02-22 15:44:56
* @Last Modified by: laifeipeng
* @Last Modified time: 2019-02-22 16:29:36
*/
/*************** 观察者模式 **************/
// 观察的主题(目标对象),相当于发布者
class Subject {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
console.log(this.subs)
}
removeSub(sub) {
const idx = this.subs.findIndex(i => i === sub);
if (idx === -1) {
console.log('不存在该观察者');
return;
}
this.subs.splice(idx, 1);
}
notify() {
this.subs.forEach(sub => {
sub.update();// 与观察者原型方法update对应!
});
}
}
// 观察人,相当于订阅者
class Observer {
update() {
console.log('update');
}
}
// 测试代码
const subject = new Subject();
const ob = new Observer();
const ob2 = new Observer();
ob2.update = function () { //修改update方法,实现不同逻辑
console.log('laifeipeng');
}
//目标添加观察者了
subject.addSub(ob);
subject.addSub(ob2);
//目标发布消息调用观察者的更新方法了
subject.notify();
// update
// laifeipeng
subject.removeSub(ob2); //移除之后就不触发ob2的update了,不再打印`laifeipeng`
subject.notify();
// update
const test = new Observer();
subject.removeSub(test);//
// 不存在该观察者
复制代码
2、根据内部状态自动触发更新
- 手动触发有啥用?肯定要根据内部状态更改触发才有用!
- 增加内部状态变量state并增加对应的getter/setter
/*
* @Author: laifeipeng
* @Date: 2019-02-22 15:44:56
* @Last Modified by: laifeipeng
* @Last Modified time: 2019-02-22 16:29:36
*/
/*************** 观察者模式 **************/
// 观察的主题(目标对象),相当于发布者
class Subject {
constructor() {
this.subs = [];
this.state = "张三";//触发更新的状态
}
//新增两个对于name的操作 获取/更新
getState() {
return state;
}
setState(state) {
if (this.state === state) {
console.log('不能设为之前的name,无效');
return;
}
this.state = state;
this.notify(); // 有更新,触发通知!【原本手动触发通知的,现在根据数据变化来触发】
}
addSub(sub) {
this.subs.push(sub);
console.log(this.subs)
}
removeSub(sub) {
const idx = this.subs.findIndex(i => i === sub);
if (idx === -1) {
console.log('不存在该观察者');
return;
}
this.subs.splice(idx, 1);
}
notify() {
this.subs.forEach(sub => {
sub.update();// 与观察者原型方法update对应!
});
}
}
// 观察人,相当于订阅者
class Observer {
update() {
console.log('update');
}
}
// 测试代码
const subject = new Subject();
const ob = new Observer();
const ob2 = new Observer();
ob2.update = function () { //修改update方法,实现不同逻辑
console.log('laifeipeng');
}
//目标添加观察者了
subject.addSub(ob);
subject.addSub(ob2);
//目标发布消息调用观察者的更新方法了
// subject.notify(); // 不使用手动触发,通过内部状态的设置来触发
subject.setState('李四');
// update
// laifeipeng
subject.setState('李四');
// 不能设为之前的name,无效
复制代码
3、观察外部的对象
- 在2的基础上,把内部状态改为外部的对象(变量)。
- 举例:贪吃蛇页面score分数,根据snake的长度而改变。
- 下面只写基本的框架,其他自行填充。
// 贪吃蛇
class Snake(){
constructor(){
this.length=3;// 初始长度
// ...其他一系列实例属性
}
// ...其他一系列原型方法
}
const snake = new Snake();
//...对snake的各种处理
class Subject {
constructor(obj) {
this.subs = [];
this.state = obj.length;//触发更新的状态
}
notify() {
this.subs.forEach(sub => {
sub.update(n);// 与观察者原型方法update对应!
});
}
// 其他还是原来的
}
class Observer {
constructor(obj) {
this.score = obj.value;//触发更新的状态
}
update(n) {
this.score += n;
}
}
const subject = new Subject(snake);
const ob = new Observer(document.getElementById('score'));
subject.addSub(ob);
// 大功告成!!!
复制代码
3、发布订阅模式
- 下次更新