博客
电影
宝箱
友链
关于
<
《李尔王》与《乱》影评,人性的悲歌
《荷马史诗·奥德赛》读后感
>
ES6设计模式之观察者模式
作者:
Cifer
类别: 技术·JS
时间:2018-07-11 02:04:52
字数:3795
版权所有,未经允许,请勿转载,谢谢合作~
附: [ES6设计模式之工厂模式](http://www.boatsky.com/blog/22.html "ES6设计模式之工厂模式") [ES6设计模式之单例模式](http://www.boatsky.com/blog/23.html "ES6设计模式之单例模式") ### 观察者模式 Observer [观察者模式](http://www.boatsky.com/blog/40.html "ES6设计模式之观察者模式"),是指一个目标维护一系列观察者,每当有状态变化时则自动通知给这些依赖于该目标的观察者们。 一般其有四种组件: 目标 Subject,维护观察者,抽象化,与业务无关。 观察者 Observer,抽象观察者,抽象化,与业务无关。 具体目标 ConcreteSubject,继承目标,对具体观察者通知,具体业务的数据获取、处理与通知中心。 具体观察者 ConcreteObserver,继承观察者,须实现统一通知接口,以便被具体目标更新数据,也是具体业务的数据展示。 2018年的世界杯接近尾声,我们不妨以其为例,使用观察者模式实现积分排名与进球排名这个功能。 其中已知世界杯数据openAPI接口 ,每条数据长这样: ```javascript { id: 15, country: "Croatia", alternate_name: null, fifa_code: "CRO", group_id: 4, group_letter: "D", wins: 3, draws: 2, losses: 0, games_played: 5, points: 11, goals_for: 10, goals_against: 4, goal_differential: 6 }, ``` 我们只需使用积分points与得分goals_for排名即可。 #### 目标 Subject ```javascript // 抽象目标,维护观察者,与业务无关 class Subject { constructor() { this.observers = []; } registerObserver(obs) { this.observers.push(obs); } removeObserver(obs) { let i = this.observers.indexOf(obs); if (i > -1) { this.observers.splice(i, 1) } } } ``` #### 观察者 Observer ```javascript // 抽象观察者 class Observer { // 初始化时注册观察者 constructor(concreteSubject) { if (concreteSubject) { concreteSubject.registerObserver(this); } } // 快速排序 quickSort(arr, key) { if(Object.prototype.toString.call(arr) !== '[object Array]' || arr.length <=1){ return arr; } var largeArr = [],smallArr = [],len = arr.length; var pivot = arr[0]; for (var i = 1; i < len; i++) { if (arr[i][key] < pivot[key]) { smallArr.push(arr[i]); } else { largeArr.push(arr[i]); } } return this.quickSort(largeArr, key).concat(pivot, this.quickSort(smallArr, key)); } } ``` #### 具体目标 ConcreteSubject ```javascript // 具体目标,对具体观察者通知 class ConcreteSubject extends Subject { // 每当数据变化,都会通知所有观察者 set data(data) { this.notifyObservers(data); } notifyObservers(data) { for (let i = 0;i < this.observers.length;i++) { this.observers[i].update(data); } } } ``` #### 世界杯积分排名-观察者 PointsObserver ```javascript // 世界杯积分排名-观察者,须实现统一通知接口update class PointsObserver extends Observer { update(data) { this.renderHtml(this.quickSort(data, 'points')); } renderHtml(arr) { let html = ''; for (let i = 0;i < arr.length;i++) { html = html + `<tr><td>${i+1}</td><td>${arr[i].country}</td><td>${arr[i].group_letter}</td><td>${arr[i].points}</td></tr>`; } document.getElementById('points').innerHTML = html; } } ``` #### 世界杯进球排名-观察者 GoldsObserver ```javascript class GoldsObserver extends Observer { update(data) { this.renderHtml(this.quickSort(data, 'goals_for')); } renderHtml(arr) { let html = ''; for (let i = 0;i < arr.length;i++) { html = html + `<tr><td>${i+1}</td><td>${arr[i].country}</td><td>${arr[i].group_letter}</td><td>${arr[i].goals_for}</td></tr>`; } document.getElementById('goals_for').innerHTML = html; } } ``` #### 运行上述结果,每120s 重新获取一次数据: ```javascript let concreteSubject = new ConcreteSubject(); // 初始化注册 let pointsObserver = new PointsObserver(concreteSubject); let goldsObserver = new GoldsObserver(); // 后续注册 concreteSubject.registerObserver(goldsObserver); function getAjax(url){ var xmlHttp; if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } else if (window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlHttp.open("GET", url, true); xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xmlHttp.send(null); xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4){ if(xmlHttp.status == 200){ var responseObj = JSON.parse(xmlHttp.responseText); // 更新世界杯数据 concreteSubject.data = responseObj; } } }; } let url = 'https://worldcup.sfg.io/teams/results'; getAjax(url); setInterval(function(){ getAjax(url); }, 120000); ``` 最后贴上以上demo: [观察者模式实现2018年世界杯积分与进球排名](http://www.boatsky.com/demo/pattern/observer.html "观察者模式实现2018年世界杯积分与进球排名")
如果觉得有帮忙,您可以在本页底部留言。
相关推荐:
NPM发包流程与技巧
Puppeteer爬取豆瓣电影TOP250评分
基于vue实现腾讯云点播的上传与播放
JS代理Proxy与反射Reflect场景
轻应用PWA实践全过程
ES6迭代器Iterator原理与性能
JavaScript之Set与Map
解决toFixed四舍五入陷阱
深入理解IEEE754的64位双精度
ES6设计模式之单例模式
ES6设计模式之工厂模式
ES6二叉树的实现
JavaScript链表实例
JavaScript排序算法及性能比较
原生ajax及jQuery封装ajax实例
JavaScript类的语法糖
……
更多
<
《李尔王》与《乱》影评,人性的悲歌
《荷马史诗·奥德赛》读后感
>
全部留言
我要留言
内容:
网名:
邮箱:
个人网站:
发表
全部留言