核心提示:解决的问题代码中,通常有这样的一种需求。几个松散耦合的对象,或者组件,如何进行有效的通信,或者说,当其中的一条数据改变,其他组件的相应数据也会跟着改变,我们该如何实现?观察者模式,通常是用来解决这一类...
解决的问题
代码中,通常有这样的一种需求。几个松散耦合的对象,或者组件,如何进行有效的通信,或者说,当其中的一条数据改变,其他组件的相应数据也会跟着改变,我们该如何实现?
观察者模式,通常是用来解决这一类的问题的!
概念
观察者模式的概念是什么?
一个或者多个对象如果对目标的状态感兴趣,通常会将自己依附在这个对象上,以便于获取自己感兴趣的内容。当目标状态发生改变,就会发送一个通知消息,调用每个观察者的更新方法。
实现
观察者模式可以简单的使用这样的几个组件来实现它。
Subject——维护一系列观察者,方便添加或者删除观察者。
Observer——为那些目标状态发生改变时的观察者提供一个更新的接口。
ConcreteSubject——状态发生改变时,向Observer发送通知,存储一种状态。
ConcreteObserver——存储一个指向ConcreteSubject的引用,实现Observer的更新接口。
示例
本示例实现了一个点击产生随机数并在不同的页面同时得到通知的效果。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #box{ width: 200px; height: 400px; border: 1px solid #cccccc; } .content{ width: 200px; height: 350px; } .home{ display: block; } .me{ display: none; } .footer{ height: 50px; display: flex; } .flex1{ flex: 1; } .center{ display: flex; justify-content: center; align-items: center; } </style> <script> //定义维护observers的数组 function ObserverList() { this.observerList = []; } ObserverList.prototype.add = function (obj) { this.observerList.push(obj) } ObserverList.prototype.count = function (obj) { return this.observerList.length } ObserverList.prototype.change = function (context) { for(var i = 0; i < this.observerList.length; i++){ this.observerList[i].update(context); } } //定义观察者 function Subject() { this.Observers = new ObserverList(); } Subject.prototype.AddObservers = function (obj) { this.Observers.add(obj) } Subject.prototype.Change = function (value) { this.Observers.change(value) } function extend(obj, extension) { for(var key in obj){ extension[key] = obj[key]; } } </script> </head> <body> <p id="box"> <p class="content"> <p class="content home"> shouye <p id="left">click改变数字</p> <p id="num1">1</p> </p> <p class="content me"> wode <p id="num2">2</p> </p> </p> <p class="footer"> <p class="flex1 center" id="home">首页</p> <p class="flex1 center" id="me">我的</p> </p> </p> </body> <script> var home = document.getElementById('home'); var me = document.getElementById('me'); home.onclick = function () { document.getElementsByClassName('home')[0].style.display = 'block'; document.getElementsByClassName('me')[0].style.display = 'none'; } me.onclick = function () { document.getElementsByClassName('home')[0].style.display = 'none'; document.getElementsByClassName('me')[0].style.display = 'block'; } var left = document.getElementById('left'); //这部分开始和观察者相关了 extend(new Subject(), left); var num1 = document.getElementById('num1'); var num2 = document.getElementById('num2'); //添加到数组中 left.AddObservers(num1); left.AddObservers(num2); //定义更新函数。 num1.update = function (value) { num1.innerHTML = value } num2.update = function (value) { num2.innerHTML = value } left.onclick = function () { var num = Math.floor(Math.random() * 10); this.Change(num);//调用change函数进行广播。 } </script> </html>