1、 观察者模式的定义
观察者模式又叫发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某个主体对象。这个主体对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
2、 观察者模式的类图结构
Client:调用客户端
Subject:主题抽象类
ConcreteSubject:具体主题类
Observer:观察者抽象类
ConcreteObserver:观察者具体类
3、 模式的优缺点及适用范围
面向对象编程将一个系统分割成一系列相互协作的类,有一个很不好的副作用,那就是需要维护对象之间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。而观察者的关键对象是主题和观察者,一个主题可以有任意数目的依赖它的观察者,一旦主题发生了变化,所有的观察者都可以得到通知。主题发出通知的时候并不需要知道谁是它的观察者。而任何一个具体的观察者不知道也不需要知道其他观察者的存在。
总的来说,观察者模式所做的工作其实就是在解耦。让耦合的双方都依赖于抽象,而不十分依赖于具体。从而使得各自的变化都不会影响到另一边。
4、 模式应用举例
最近股票很火引得很多同事争相入市,带来的一个不良影响就是工作的时候总想掏出手机看看自己的股票的涨跌情况,但是恐于顶头上司和自己坐的很近,这样常常翻看股票信息会给领导留下不好的印象,因此很希望有一个提醒的小工具,当股票变化达到预先设定情况时,能即使发给注册过的人发一条信息,提醒及时操作。这样注册过的人就不用整天盯盘,从而专心工作。这个情况,可以用观察者模式模拟如下:
#include<iostream>
#include<vector>
using namespace std;
class Stock;
class Register{
public:
Register(Stock* stock);
void update();
void setPare(char* name, double downRate, double upRate);
private:
char* name;
double downRate;
double upRate;
Stock* stock;
};
class Stock{
public:
void add(Register* person);
void remove(Register* person);
void notify();
void updateRate(double rate);
double getRate();
Stock(char* name);
char* getStockName();
protected:
vector<Register*> registerList;
private:
double rate;
char* stockName;
};
Register::Register(Stock* stock){
this->stock = stock;
}
void Register::update(){
double rate = stock->getRate();
if(rate >= upRate){
cout<<"赚钱啦,赶紧抛掉!-- "<<stock->getStockName()<<"--"<<*name<<endl;
}else if(rate <= downRate){
cout<<"割肉啦,赶紧抛掉!-- "<<stock->getStockName()<<"--"<<*name<<endl;
}
}
void Register::setPare(char* name, double downRate, double upRate){
this->downRate = downRate;
this->upRate = upRate;
this->name = name;
}
void Stock::notify(){
int size = registerList.size();
for(int i = 0; i < size; i++ ){
registerList[i]->update();
}
}
void Stock::updateRate(double rate){
this->rate = rate;
notify();
}
double Stock::getRate(){
return rate;
}
Stock::Stock(char* name){
stockName = name;
}
char* Stock::getStockName(){
return stockName;
}
void Stock::add(Register* person){
vector<Register*>::iterator iter;
iter = find(registerList.begin(), registerList.end(), person);
if(iter == registerList.end()){
registerList.push_back(person);
}
}
void Stock::remove(Register* person){
vector<Register*>::iterator iter;
iter = find(registerList.begin(), registerList.end(), person);
if(iter != registerList.end()){
registerList.erase(iter);
}
}
int main(){
Stock* zteStock = new Stock("zte");
Stock* tencentStock = new Stock("tencent");
Register* shuang = new Register(zteStock);
shuang->setPare("shuangdaguanren",-20,10);
zteStock->add(shuang);
Register* tang = new Register(tencentStock);
tang->setPare("tangdaguanren",-30,10);
tencentStock->add(tang);
zteStock->updateRate(20);
tencentStock->updateRate(50);
return 0;
}