JavaScript设计模式之观察者模式(学习笔记)
设计模式(Design Pattern)对于软件开发来说其重要性不言而喻,代码可复用、可维护、可扩展一直都是软件工程中的追求!对于我一个学javascript的人来说,理解设计模式似乎有些困难,对仅切图、做少量交互效果的FE甚至可能不会用到,但是当你开始使用Angular/Backbone等框架的时候,就无法避免设计模式、MVC/MVVM这些东西了(反正我是伤脑筋)。
我学设计模式是刚开始接触编程大概三个月的时候,看一本书《大话设计模式》,里面用C#语言来写,我很无语,因为强类型的编程语言对于我这种写弱类型的毛头小子来说,似乎又有困难啊,于是我就学C#基础语法规则去了。。。今年年初我又学了JAVA的基础语法规则。。。然而我的初衷已经被抛弃在一旁,落上了厚厚的灰层。对于自学编程的我来说,不知道学习编程的先后顺序似乎吃亏不少,但是总要有开头的!
以上可直接跳过
先来说一下我对“观察者模式”的个人理解:观察者模式又称“发布-订阅(Publish/Subscribe)模式”,发布与订阅显然是两个不同对象的功能,比如RSS。知乎是一个发布者(发布一些对某方面问题的高赞同解答),我作为一个订阅者(在我的邮箱里面订阅了知乎的相关发布内容),我的同事以及我的老板都订阅了知乎,所以在这个模型中,有一个发布者,有三个订阅者。
在具体编程中,发布者有了新的内容,需要向订阅者推送数据,那么新的内容(state)、订阅者有哪些(observers)就是发布者需要包含的东西,谁订阅了、谁退订了则要对发布者中的订阅者列表进行更新。以下是发布者的相关信息代码解读:
//发布者
function Publisher(){
this.observers = [];
this.state = ""; }
Publisher.prototype.addOb=function(observer){
var flag = false;
for (var i = this.observers.length - 1; i >= 0; i--) {
if(this.observers[i]===observer){
flag=true;
}
};
if(!flag){
this.observers.push(observer);
}
return this;
}
Publisher.prototype.removeOb=function(observer){
var observers = this.observers;
for (var i = 0; i < observers.length; i++) {
if(observers[i]===observer){
observers.splice(i,1);
}
};
return this;
}
Publisher.prototype.notice=function(){
var observers = this.observers;
for (var i = 0; i < observers.length; i++) {
observers[i].update(this.state);
};
}
以上在遍历observers数组的时候,可以使用数组类的filter、forEach等新特性来处理。第三个notice函数表示发布者有了新东西,然后对订阅者列表中的所有人通知他们我有新内容(state)了,你们拿去更新你们的邮箱吧。这里把内容传递给了每一个订阅者的update更新功能。
那么订阅者呢?订阅者很简单,只需要具有一个update功能即可(每一个订阅者update可能不一样,比如我是放进邮箱了,我的同事则将订阅的拿来,并且顺便把旧的删掉了,我的上司则将数据转发到Gmail去了)。下面是订阅者相关信息代码解读:
//订阅者
function Subscribe(){
this.update = function(data){
console.log(data);
};
}
实际上,因为每一个订阅者都有这个update,所以我们通常应该将其添加到构造器的原型上面,当对这个默认的update功能不满足要求的时候,可以为每一个订阅者的实例设置单独的update,比如将这个data发送给别人。最后咱们看看怎么应用。
//实际应用
var oba = new Subscribe(),
obb = new Subscribe(); var pba = new Publisher(); pba.addOb(oba);
pba.addOb(obb); oba.update = function(state){
console.log(state+"hello!");
}
obb.update = function(state){
console.log(state+"world!");
}
pba.state = "open ";
pba.notice();
大家看到,我们在最后对发布者手动设置了它的内容(state)并且要求他发出通知(notice)。在实际项目中,发布者的内容可能是从后台获取的也可能是从前台某地方输入的。然而发布者每次更新内容后又要手动调用通知是不是有点多余呢?既然更新了内容那就肯定要通知别人了啊。那我们就把内容的更新与发出通知进行绑定好了,看下面的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
//发布者
function Publisher(){
this.observers = [];
var state = ""; //让该内容不能直接访问 //新增两个对于state的操作 获取/更新
this.getState=function(){
return state;
}
this.setState=function(value){
state = value;
this.notice();
} }
Publisher.prototype.addOb=function(observer){
var flag = false;
for (var i = this.observers.length - 1; i >= 0; i--) {
if(this.observers[i]===observer){
flag=true;
}
};
if(!flag){
this.observers.push(observer);
}
return this;
}
Publisher.prototype.removeOb=function(observer){
var observers = this.observers;
for (var i = 0; i < observers.length; i++) {
if(observers[i]===observer){
observers.splice(i,1);
}
};
return this;
}
Publisher.prototype.notice=function(){
var observers = this.observers;
for (var i = 0; i < observers.length; i++) {
observers[i].update(this.getState()); //获取发布者的内容
};
} //订阅者
function Subscribe(){
this.update = function(data){
console.log(data);
};
} //实际应用
var oba = new Subscribe(),
obb = new Subscribe(); var pba = new Publisher(); pba.addOb(oba);
pba.addOb(obb); oba.update = function(state){
console.log(state+"hello!");
}
obb.update = function(state){
console.log(state+"world!");
}
pba.setState("open "); //发布者更新了内容
</script>
</body>
</html>
对于以上的内容,或许并没有跟我们的项目中实际出现的问题有关,那我们就来代入这种设计模式,做一个例子:三个文本框ABC,其中A可编辑,B与C不可编辑且B的值是A的值加上后缀"@w3c.com",C的值是A的值加上前缀"ID-"。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<label>用户名称:<input type="text" id="pba" placeholder="请输入用户名称" /></label><br /><br />
<label>生成邮箱:<input type="text" id="oba" readonly /></label>
<label>生成ID:<input type="text" id="obb" readonly /></label>
</div> <script type="text/javascript">
//发布者
function Publisher(obj){
this.observers = [];
var state = obj.value; //让该内容不能直接访问 //新增两个对于state的操作 获取/更新
this.getState=function(){
return state;
}
this.setState=function(value){
state = value;
this.notice();
}
this.obj = obj; }
Publisher.prototype.addOb=function(observer){
var flag = false;
for (var i = this.observers.length - 1; i >= 0; i--) {
if(this.observers[i]===observer){
flag=true;
}
};
if(!flag){
this.observers.push(observer);
}
return this;
}
Publisher.prototype.removeOb=function(observer){
var observers = this.observers;
for (var i = 0; i < observers.length; i++) {
if(observers[i]===observer){
observers.splice(i,1);
}
};
return this;
}
Publisher.prototype.notice=function(){
var observers = this.observers;
for (var i = 0; i < observers.length; i++) {
observers[i].update(this.getState());
};
} //订阅者
function Subscribe(obj){
this.obj = obj;
this.update = function(data){
this.obj.value = data;
};
} //实际应用
var oba = new Subscribe(document.querySelector("#oba")),
obb = new Subscribe(document.querySelector("#obb")); var pba = new Publisher(document.querySelector("#pba")); pba.addOb(oba);
pba.addOb(obb); oba.update = function(state){
this.obj.value = state+"@w3c.com";
}
obb.update = function(state){
this.obj.value = "ID-"+state;
} pba.obj.addEventListener('keyup',function(){
pba.setState(this.value);
}); </script>
</body>
</html>
在《大话设计模式》一书中,提到类似的情况:如果针对发布者内容而订阅者要做不同的事情呢?比如一个按钮和三个矩形,点击按钮的时候,第一个矩形增加宽度,第二个矩形增加高度,第三个矩形则变成圆角矩形又该怎么做呢?当然我们可以在三个矩形的update内部写具体的实现代码,但是这update岂不是没有一个具体的功能描述了吗?该书中用“事件委托”解决了这个问题(此处事件委托和DOM中的事件委托应该是两码事),我个人理解这个“事件委托”在javascript中可以用一个数组表示,然后里面放各个订阅者的不同名字的update,然后一一调用。
在《javascript设计模式》一书中,关于观察者模式的实现也是采用”推“这种方式,章节的最后反问到如何实现”拉“这种方式呢?
我个人理解:发布者推送数据的时候有强制性,促使订阅者更新(update),然而在”拉“这种模式中,发布者本身仅仅包含最新的内容,没有通知(notice)没有订阅者列表,当订阅者需要得到数据的时候在其对应的update方法里面传入发布者对象即可。小白之见,请对该模式有不同理解的道友多多指正。o(∩_∩)o
JavaScript设计模式之观察者模式(学习笔记)的更多相关文章
- [GeekBand] 设计模式之观察者模式学习笔记
本文参考文献::GeekBand课堂内容,授课老师:李建忠 :网络资料: http://blog.csdn.net/hguisu/article/details/7556625 本文仅作为自己的学习笔 ...
- 《零基础学JavaScript(全彩版)》学习笔记
<零基础学JavaScript(全彩版)>学习笔记 二〇一九年二月九日星期六0时9分 前期: 刚刚学完<零基础学HTML5+CSS3(全彩版)>,准备开始学习JavaScrip ...
- 再起航,我的学习笔记之JavaScript设计模式18(观察者模式)
观察者模式 观察者模式(Observer): 又被称为发布-订阅者模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合. 创建一个观察者对象 首先我们创建一个闭包对象,让其在页面加 ...
- 《JavaScript语言精粹》学习笔记
一.in的用法 for...in 枚举一个对象的所有可枚举属性 检测DOM/BOM属性 if ("onclick" in elem) { // 元素支持onclick } if ( ...
- 《JavaScript高级程序设计》学习笔记12篇
写在前面: 这12篇博文不是给人看的,而是用来查的,忘记了什么基础知识,点开页面Ctrl + F关键字就好了 P.S.如果在对应分类里没有找到,麻烦告诉我,以便尽快添上.当然,我也会时不时地添点遗漏的 ...
- 《JavaScript权威指南》学习笔记 第六天 开始学习DOM了。
昨天学习了window对象的一些方法.window对象主要是针对当前视窗的操作.window对象提供了一些列API来帮助我们了解当前窗口的信息.例如history对象可以让我们获取浏览历史.nvaig ...
- Ruby设计模式-观察者模式学习笔记
observer.rb #!/bin/env ruby # encoding: utf-8 require 'observer' class CriminalMovement include Obse ...
- 《JavaScript高级程序设计》学习笔记(5)——面向对象编程
欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 本节内容对应<JavaScript高级程序设计>的第六章内容. 1.面向对象(Object ...
- 《JavaScript权威指南》学习笔记 第五天 window对象的方法。
前天和昨天大致浏览了犀牛书的函数.类与模块.正则表达式.JavaScript扩展.以及服务端的js.这些方面对于我目前的水平来说比较难,一些最基本的概念都不能领会.不过最复杂的知识占用平时使用的20% ...
随机推荐
- const 笔记
.指向const的指针例如:double a=1.01;const double * b=&a;*b=2.1; //这显然是错误的a=2.1; //这是正确的,a和*b的值都会变成2.01,有 ...
- net programming guid
Beej's Guide to Network Programming Using Internet Sockets Brian "Beej Jorgensen" Hallbeej ...
- Web工程软件升级之数据库升级(一)
1. 首先检查oracle数据库版本是否正确 (可以使用方法 lsinventory来实现) 2. 检查oracle连接是否成功 3. 解压升级包,放到特定目录 4. 做升级前数据备份,备份主要业务数 ...
- 解决Ext.TextField的AllowBlank不能过滤空格代码
Ext过滤空格 重写了组件... Ext.apply(Ext.form.TextField.prototype, { validator : function(text) { if (this.all ...
- 获取Delphi所有类的类信息
Delphi遍历进程中所有Class的TypeInfo,即便是在implementation中的class或者其他 class的private的子class. 一般普通EXE中的TypeInfo存放在 ...
- java中String s="abc"及String s=new String("abc")详解
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度比堆要快,仅次于直 ...
- 【HDOJ】1818 It's not a Bug, It's a Feature!
状态压缩+优先级bfs. /* 1818 */ #include <iostream> #include <queue> #include <cstdio> #in ...
- POJ1416 Shredding Company(dfs)
题目链接. 分析: 这题从早上调到现在.也不算太麻烦,细节吧. 每个数字都只有两种状态,加入前一序列和不加入前一序列.DFS枚举. #include <iostream> #include ...
- 【转】如何在github上fork一个项目来贡献代码以及同步原作者的修改 -- 不错
原文网址:http://www.cnblogs.com/astwish/articles/3548844.html 作为一个IT人,通过github进行学习是最快的成长手段.我们可以浏览别人的优秀代码 ...
- github继续折腾
又在折腾github了,本来以前在neworiginou这个github上上传过项目的: 现在想在另一个github上joely上传项目,发现按以前的流程做个测试,居然没能上传成功! 经发现,以前的n ...