观察者模式
一个类(称为subject)根据它维护一个观察者列表,自动通知它们状态的任何更改,当subject需要通知观察者一些事件时,它会向观察者广播一个通知(其中可以包括与通知subject相关的特定数据)。当某些观察者不需要得到通知时,需要移除这个观察者。
代码
class ObserverList {
constructor() {
this.observerList = [];
}
add(observer) {
return this.observerList.push(observer);
}
remove(observer) {
this.observerList = this.observerList.filter(ob => ob !== observer);
}
count() {
return this.observerList.length;
}
get(index) {
return this.observerList[index];
}
}
class Subject {
constructor() {
this.observers = new ObserverList();
}
addObserver(observer) {
this.observers.add(observer);
}
removeObserver(observer) {
this.observers.remove(observer);
}
notify(args) {
let observerCount = this.observers.count();
for (let i = 0; i < observerCount; i++) {
this.observers.get(i).update(args);
}
}
}
注意:
observerlist 提供一个get,count方法,是为了让每个类更关注自己的部分,这时候,suject调用,就不用关心observerlist的数据解构问题,反而不提供get方法,则suject就需要关心观察者的数据解构。
测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button id="addNewObserver">添加观察者</button>
<input id="mainCheckbox" type="checkbox"/>发送通知
<div id="observersContainer"></div>
<script src="./observable.js"></script>
<script>
//观察者
class Observer {
update(){}
}
const subject=new Subject();
const controlCheckbox = document.getElementById("mainCheckbox"),
addBtn = document.getElementById("addNewObserver"),
container = document.getElementById("observersContainer");
//发送通知
controlCheckbox.addEventListener("click",function(){
subject.notify(controlCheckbox.checked);
})
addBtn.addEventListener("click",function(){
var check = document.createElement("input");
check.type = "checkbox";
const ob=new Observer;
//实例化一个观察者
Object.assign(check,new Observer())
//提供一个更新的接口
check.update=function(value){
this.checked = value;
}
//添加观察者
subject.addObserver(check);
container.appendChild(check);
})
</script>
</body>
</html>
效果图
发布/订阅模式
发布/订阅模式就是使用一个通道,该通道用来接受订阅者自定义的事件和处理函数,然后发布者也是通过这个通道,找到对应的事件,触发事件当中所有的处理函数。
代码
class PubSub {
constructor() {
this.subscribers = {};
}
subscribe(type, fn) {
let listeners = this.subscribers[type] = this.subscribers[type] || [];
listeners.push(fn);
}
unsubscribe(type, fn) {
let listeners = this.subscribers[type];
if (!listeners) return;
this.subscribers[type] = listeners.filter(listener => listener !== fn);
}
publish(type, args) {
let listeners = this.subscribers[type];
if (!listeners) return;
listeners.forEach(listener => listener(args));
}
}
测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button id="addNewObserver">订阅</button>
<input id="mainCheckbox" type="checkbox" />发布
<div id="observersContainer"></div>
<script src="./PubSub.js"></script>
<script>
const pubSub = new PubSub();
const controlCheckbox = document.getElementById("mainCheckbox"),
addBtn = document.getElementById("addNewObserver"),
container = document.getElementById("observersContainer");
//发布
controlCheckbox.addEventListener("click", function () {
pubSub.publish("pu", controlCheckbox.checked);
})
addBtn.addEventListener("click", function () {
var check = document.createElement("input");
check.type = "checkbox";
//订阅
const update = function (value) {
this.checked = value;
}.bind(check);
pubSub.subscribe("pu", update)
container.appendChild(check);
})
</script>
</body>
</html>
效果图和观察者模式一样,所以这里就不贴了,另外需要注意的是,测试里面引得脚本需要自己定义哦。
最后谢谢大家的查阅!!