PHP设计模式——观察者模式

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>
原文地址:https://www.cnblogs.com/tlxma/p/5210696.html