PHP版本
<?php /** * 观察者模式 * 观察者模式能够便利的创建查看目标对象状态的对象,并且提供与核心对象非耦合的指定性功能。 * * 为软件添加由某个动作或状态变化激活的,但是松散耦合的新功能时,应当创建基于观察者模式的对象。 * * SPL:Standard PHP Library PHP标准库 */ class User implements SplSubject{ public $lognum; public $hobby; protected $_observers = NULL; public function __construct($hobby) { $this->lognum = rand(1,10); $this->hobby = $hobby; $this->_observers = new SplObjectStorage(); } public function login() { $this->notify(); } public function attach(SplObserver $observer) { $this->_observers->attach($observer); } public function detach(SplObserver $observer) { $this->_observers->detach($observer); } public function notify() { $this->_observers->rewind(); while ($this->_observers->valid()) { $observer = $this->_observers->current(); $observer->update($this); $this->_observers->next(); } } } /** * 功能模块 */ class Login implements SplObserver{ public function update(SplSubject $subject) { echo "登录次数:".$subject->lognum.'<br>'; } } //实施观察 $user = new User('学习'); $user->attach(new Login()); $user->login(); //添加模块 class Hobby implements SplObserver{ public function update(SplSubject $subject) { echo "爱好:".$subject->hobby; } } $hobby = new Hobby; $user->attach($hobby); $user->login(); echo '<br>'; //删除观察模块 $user->detach($hobby); $user->login();
JS版本
<!DOCTYPE html> <!-- To change this license header, choose License Headers in Project Properties. To change this template file, choose Tools | Templates and open the template in the editor. --> <html> <head> <title>观察者模式</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> div{border:solid gray 1px;margin-top:10px;height: 100px;width: 200px;} </style> </head> <body> <h1>观察者模式</h1> <select> <option value="1">风格1</option> <option value="2">风格2</option> </select> <button onclick="detachC()">不观察C</button> <button onclick="attachC()">观察C</button> <!--模块一--> <div id="A">A</div> <!--模块二--> <div id="B">B</div> <!--模块三--> <div id="C">C</div> <script> //观察者 var sel = document.getElementsByTagName('select')[0]; sel.observers = {} sel.attach = function(key, obj) { this.observers[key] = obj; } sel.detach = function(key) { delete this.observers[key]; } sel.onchange = sel.notify = function() { for (var key in this.observers) { this.observers[key].update(this); } } //被观察对象及操作 var a = document.getElementById('A'); var b = document.getElementById('B'); a.update = function(observe) { if (1 == observe.value) { this.innerHTML = 'A模块:风格1'; } if (2 == observe.value) { this.innerHTML = 'A模块:风格2'; } } b.update = function(observe) { if (1 == observe.value) { this.innerHTML = 'B模块:风格1'; } if (2 == observe.value) { this.innerHTML = 'B模块:风格2'; } } //开启观察 sel.attach('a', a); sel.attach('b', b); //添加观察C模块 var c = document.getElementById('C'); c.update = function(observe) { if (1 == observe.value) { this.innerHTML = 'C模块:风格1'; } if (2 == observe.value) { this.innerHTML = 'C模块:风格2'; } } sel.attach('c', c); //取消观察 function attachC(){ sel.attach('c',c); } function detachC(){ sel.detach('c'); } </script> </body> </html>