<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>观察</title>
</head>
<style>
div{
width: 80%;
height: 300px;
border: 1px solid blue;
margin: 10px;
}
</style>
<body>
<select name="sel" id="sel">
<option value="0">男士广告</option>
<option value="1">女士广告</option>
</select>
<input type="button" onclick="drop()" value="不再观察购物频道">
<div id="test2">新闻</div>
<div id="test3">购物</div>
</body>
<script>
var sel = document.getElementById('sel');
sel.observers = [];
sel.attach = function (obj){
sel.observers[this.observers.length] = obj;
}
sel.detach = function (obj){
for (var i=0;i < this.observers.length; i++){
if(this.observers[i] === obj){
delete this.observers[i];
}
}
}
sel.onchange = sel.notify = function (){
for (var i=0;i < this.observers.length;i++){
if(this.observers[i]){
this.observers[i].update(this);
}
}
}
var test2 = document.getElementById('test2');
var test3 = document.getElementById('test3');
sel.attach(test2);
sel.attach(test3);
test2.update = function (sel){
if(sel.value=='1'){
this.innerHTML = '明星八卦';
}else if(sel.value=='0'){
this.innerHTML = '德国足球';
}
}
test3.update = function (sel){
if(sel.value=='1'){
this.innerHTML = '化妆品护肤品';
}else if(sel.value=='0'){
this.innerHTML = '大众汽车';
}
}
function drop (){
sel.detach(test3)
}
</script>
</html>
上述点击选择按钮,下面的方块显示对应的内容,当然也可以选择不再观察其中的某个方块对象
<?php
interface Observer{
public function update($data);
}
class Message implements Observer{
public function update($data)
{
// TODO: Implement update() method.
echo '发送短信通知变化'.$data['uid'];
}
}
class Goods implements Observer{
public function update($data)
{
// TODO: Implement update() method.
echo '修改商品库存'.$data['goods_id'];
}
}
class Order{
protected $observers = [];
public $data = [];
public function __construct($uid,$goods_id){
$this->data = [
'uid'=>$uid,
'goods_id'=>$goods_id
];
}
public function attach($obj){
$this->observers[] = $obj;
}
public function detach($obj){
foreach ($this->observers as $k=>$v){
if($v===$obj){
unset($this->observers[$k]);
}
}
}
public function notify(){
foreach ($this->observers as $obj){
$obj->update($this->data);
}
}
}
$message = new Message();
$goods = new Goods();
$order = new Order('4444','1128');
$order->attach($message);
$order->attach($goods);
$order->notify();
$order->detach($message);
$order->notify();
Order的实现类,只是更新了状态,在这个状态发生改变的时候,调用观察者遍历的方法进行所有观察的update()操作
- 观察者,其实就是自身做了一个更新(update),而Order,可以批量的执行观察者,请注意,我们不需要去修改目标类中的任何代码,只需要从外部添加就可以了,所以就让目标和观察者解耦互相之间不用关心对方的情况了
- 观察者可以记录目标的状态,也可以不用记录,比如我们发完短信后的数据库更新或者插入操作,只有短信接口发送成功后我们再修改短信数据的状态就可以了,不一定完全需要将目标的发送状态传送给观察者
- 当一个类在发生改变时,不知道可能会对其他多少类产生影响,这个时候观察者非常有用
- 观察者模式中还是存在着耦合,那就是目标类中有一个观察者对象列表,如果观察者没有实现update()方法,那么就会出现问题