设计模式初探2——观察者模式(Observer Pattern)

观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。


典型使用情况:某个对象掌握数据,当数据更新时通知多个对象更新显示(参考MVC)。

在java内置的Observer模式中支持“push”和“pull”两种方式,一般好像push更多一点,下面就以push为例:


UML图:



依然上一段测试代码:

一般来讲,把主题(Subject)内的数据封装成一个Class对日后的改动影响会小一点,编写代码时要尽量考虑到日后的变化。这里我们使用了一个string类型的字符串做测试,但是还是得提出来。


观察者接口需要提供一个update()方法:

#include <iostream>  
#include <algorithm>  
#include <list>  
  
using namespace std;  
  
class Observer {  
public:  
    virtual void update(string str) = 0;  
};  

然后是主题接口,主题能够注册和删除观察者,并且提供notifyObserver()函数提示所有观察者更新:

class Subject {  
public:  
    virtual void registerObserver(Observer*) = 0;  
    virtual void removeObserver(Observer*) = 0;  
    virtual void notifyObserver() = 0;  
}; 

我们假设有个Model实现了Subject:

Model内部存放了一个Observer*的list,用于管理每个注册进来的Observer,并在更新事件时对他们进行更新。

class Model : public Subject {  
public:  
    Model(){  
        info = "i haven't data";  
    }  
  
    void registerObserver(Observer* o){  
        observers.push_back(o);  
    }  
  
    void removeObserver(Observer* o)  
    {  
        list<Observer*>::iterator it = find(observers.begin(), observers.end(), o);  
        if ( it != observers.end() )  
            observers.remove(o);  
    }  
  
    void notifyObserver(){  
        list<Observer*>::iterator it = observers.begin();  
        while(it != observers.end()) {  
            (*it)->update(info);  
            ++it;  
        }  
    }  
    // 模拟数据发生改变  
    void dataChanged(){  
        info = "i have data now!";  
        notifyObserver();  
    }  
  
private:  
    list<Observer*> observers;  
    string info;  
};

接下来我们实现观察者,假设为View(通常会有多个观察者):

我们在构造函数中调用Subject的registerObserver将自己注册到主题中,这样主题在数据改变时就会调用View的update(),然后我们使用display()将这个数据显示出来。

class View : public Observer {  
public:  
    View(Subject* s){  
        mySubject = s;  
        mySubject->registerObserver(this);  
    }  
  
    void update(string str)  
    {  
        data = str;  
        display();  
    }  
  
    void display()  
    {  
        cout << data << endl;  
    }  
  
private:  
    Subject* mySubject;  
    string data;  
};

OK,最后来测试一下:

int main()  
{  
    Model *model = new Model();  
    View *view = new View(model);  
    model->dataChanged();  
    return 0;  
} 

以上所有代码可以放到main.cpp中直接运行,大家不要纠结这里面的内存泄露什么的。。你们懂的。。当然一般情况下可能是我们会创建多个不同的Observer对象,然后分别显示Subject中不同的数据,不过结构都大致类似啦~


最后我们在上篇博文的3个设计原则的基础上再加一条:

为交互对象之间的松耦合设计而努力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值