<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input id="pub1" type="button" value="第一报社" /><input id="text1" type="text" value="" /><br />
<input id="pub2" type="button" value="第二报社" /><input id="text2" type="text" value="" /><br />
<input id="pub3" type="button" value="第三报社" /><input id="text3" type="text" value="" /><br />
<textarea id="sub1" rows="5" cols="30"></textarea>
<textarea id="sub2" rows="5" cols="30"></textarea>
</body>
<script>
/*观察者模式:当程序中某个对象的状态发生改变的时候,进行实时的通知*/
//发布者报社 (被观察的对象)
var Publish = function(name) {
this.name = name;
//当发布者的状态发生改变时需要通知那些对象(观察者列表)
this.subscribers = []; //就是左右的订阅者 需要注意的是此处的每个订阅者 都是函数类型
}
//在当前类的原型对象上添加一个发布的方法
Publish.prototype.deliver = function(news) {
var publish = this; //因为存在 每个订阅者 可以订阅多个报社的报纸 所以将当前的报社 暂存 传给每个 订阅者
//此处的this 指的是当前发布实例 并且获取它们的每一个订阅者
this.subscribers.forEach(function(fn) { //因为每个订阅者都是函数类型
fn(news, publish); //将发布的消息 给每一个订阅者
});
return this; //将当前报社实例返回 就可以链式调用发布消息 实现链式编程
}
//订阅者
//因为每一个订阅者 都是一个函数 所以在函数的原型上扩展一个订阅的方法
Function.prototype.subscriber = function(publish) { //订阅者订阅哪家的报社?将报社作为参数传入
//此处的this指代的是当前的订阅者
var sub = this;
//获取当前报社下所有的订阅者
//some方法是循环遍历数组中的每一对象 并且执行一个函数 如果其中有一个返回true那么整体返回true 如果整体返回false 才返回false
var alreadyExists = publish.subscribers.some(function(item) { //item 是每一个函数类型的订阅者
//如果当前订阅者存在于 订阅者的列表中 就无需订阅了
//if(sub===item){
// return true;
//结束循环
//return false;
//以上代码的简写
return sub === item;
});
if(!alreadyExists) { //如果当前对象 没有在订阅者列表中 就将其添加到订阅者列表中
publish.subscribers.push(sub);
}
return this; //将当前订阅者返回 实现链式编程
}
//创建一个取消订阅的方法
Function.prototype.unsubscriber = function(publish) {
var sub = this; //当前的订阅者
//从当前报社的订阅者列表 将自己删除
//filter(过滤函数) 循环遍历数组中的每一个元素 并且执行一个函数 如果不匹配 就删除该元素 返回一个新数组
publish.subscribers = publish.subscribers.filter(function(item) {
return item !== sub; //当前遍历的元素如果不等同 当前的调用者 如果返回false 就删除该元素
});
return this;
}
window.onload = function() {
//实例化三个报社对象
var pub1 = new Publish("第一报社");
var pub2 = new Publish("第二报社");
var pub3 = new Publish("第三报社");
//实例化2个订阅者对象
var sub1 = function(news) {
Q("sub1").innerHTML = arguments[1].name + ":" + news;
}
var sub2 = function(news) {
Q("sub2").innerHTML = arguments[1].name + ":" + news;
}
//添加订阅
sub1.subscriber(pub1).subscriber(pub2).subscriber(pub3);
sub2.subscriber(pub2).subscriber(pub3);
//绑定事件
EventUtil = {
addHandler: function(element, type, handler) {
if(element.addEventListener) {
element.addEventListener(type, handler, false);
} else if(element.attachEvent) {
element.attachEvent("on" + type, handler);
}
},
removeHandler: function(element, type, handler) {
if(element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if(element.detachEvent) {
element.detachEvent("on" + type, handler);
}
}
}
function Q(ele) {
return document.getElementById(ele);
}
EventUtil.addHandler(Q("pub1"), "click", function() {
pub1.deliver(Q("text1").value);
});
EventUtil.addHandler(Q("pub2"), "click", function() {
pub2.deliver(Q("text2").value);
});
EventUtil.addHandler(Q("pub3"), "click", function() {
pub3.deliver(Q("text3").value);
});
sub1.unsubscriber(pub1);
sub2.subscriber(pub1)
}
</script>
</html>
java Script 观察者模式
最新推荐文章于 2024-08-04 16:33:59 发布