知识点回顾,上次主要说了函数式和面向对象,命令式和响应式,push 系统和 pull 系统的差异。在编程范式,风格以外,设计模式也是在程序设计中时时刻刻都在使用的东西,今天主要就讨论一下设计模式这个东西。java
模式是一种可复用的解决方案,它有三大好处:程序员
其实咱们天天都在接触模式,从最简单的facade(外观模式,jQuery,lodash为表明)到 singleton,再到MVC,模式能够说无处再也不,固然还有rxjs中使用观察者模式等。有模式,就有反模式,既然模式能够带来好处,相应的反模式就会带来坏处,在javaScript中,如下就是咱们常常见到的反模式:angularjs
在这种模式中,一个对象维持一系列依赖于它的对象,将有关的状态变动自动的通知给它们。当咱们再也不但愿某个特定的观察者获取注册目标的对象时,它能够从目标的观察者列表中移除。代码以下:编程
观察者列表类,咱们利用这个类来维护观察者的增删改查设计模式
class ObserverList { constructor() { }; list = []; add(observer) { this.list.push(observer); } count() { return this.list.length; } get(index) { if(index > -1 && index < this.list.length) { return this.list[index]; }else { return null; } } indexOf(observer, startIndex) { let i = startIndex; let pointer = -1; while( i< this.list.length) { if(this.list[i] === observer) { pointer = i; } i++; } return pointer; } removeIndexAt(index) { if(index === 0) { this.list.shift(); }else if (index === this.list.length - 1) { this.list.pop(); } } }
主题类,利用这个类来维护一个观察目标,使用观察者列表类来维护其本身的观察者,经过观察者提供的接口向外发送目标上发生的变化。app
class Subject { constructor() { this.observers = new ObserverList(); } addObserver(observer) { this.observers.add(observer); } removeObserver(observer) { this.observers.removeIndexAt(this.observers.indexOf(observer, 0)); } notify(context) { const count = this.observers.count(); for(let i = 0; i< count; i++) { this.observers.get(i).update(context); } } }
观察者类,为目标发生变化时须要得到通知的对象提供一个更新接口。函数
class Observer { constructor() { } update() { // 获取通知的接口, 不一样的observe 能够针对性的设置更新逻辑 } }
而后咱们就能够利用定义好的这些类,实现一些功能,例如,一个主checkbox,当它的状态变化时通知页面上其它的checkbox检查状态,代码大体以下:工具
HTML代码this
<button id="button">Add Observer</button> <input id="box" type="checkbox"> <div id="container"></div>
javaScript代码spa
const box = document.getElementById('box'); const btn = document.getElementById('button'); const container = document.getElementById('container'); // 工具函数 function extend(source, target) { for (let key in source) { target[key] = source[key]; } } // 利用工具函数来扩展DOM元素 extend(new Subject(), box); // 将点击事件通知给观察者 box.onclick = function { box.notify(box.checked); } btn.onclick = function addNewObserver() { const check = document.createElement('input'); check.type = 'checkbox'; extend(new Observer(), check); // 重写自定义的更新行为 check.update = (value) => this.checked = value; // 为subject的观察者列表中添加新的观察者 box.addObserver(check); // 将观察者附加到容器上 container.appendChild(check); }
观察者模式要求但愿接收通知的观察者必须订阅内容改变的事件,而发布/订阅模式中添加了一个事件通道,此通道介于订阅者和发布者之间,这样设置的主要目的是促进发布者和接收者之间的松散耦合,避免订阅者和发布者产和直接的联系,如图:
Observer Pattern
/----<--Subscribe--<--\ Subject Observer \--->--Fire Event-->--/
Publish/Subscribe Pattern
/----<--Subscribe--<--\ Publisher-->--publish-->---Event Channel Subscriber \--->---fire event-->--/
在实际的应用中, 这两种模式能够结合使用,它们都鼓励开发者思考应用程序之间不一样部分之间的关系,将应用程序分解为更小,更松散耦合的块以提升代码的复用。
优势
缺点
rxjs的实现就是创建在这两种模式的基础之上,预先要了解的基本知识经过这两篇基本上介绍完了,固然都是蜻蜓点水式的,基中任何一个点拿出来均可以长篇大论,各位若有兴趣能够找资料深刻研究。