# 本人学习时的笔记,有错必改,不喜勿喷 #
3.1 动机
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
3.2 模式定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
3.3 案例
某在线股票软件需要提供如下功能:当股票购买者所购买的某支股票价格变化幅度达到5%时,系统将自动发送通知(包括新价格)给购买该股票的股民。现使用观察者模式设计该系统,绘制类图并编程实现。
类图:
代码:
#pragma once
#include<string>
#include<vector>
#include<iostream>
using namespace std;
class Observer {
public:
virtual void notify() = 0;
};
class ConcreteObserver :public Observer {
public:
void notify() {
cout << "股票价格变化幅度达到5%了!!!" << endl;
}
};
class Stock {
public:
virtual void setPrice(double price) = 0;
virtual double getPrice() = 0;
virtual void add(Observer* observer) = 0;
virtual void change() = 0;
virtual void update() = 0;
};
class ConcreteStock :public Stock {
public:
ConcreteStock(double cur):Stock() {
this->curPrice = cur;
this->prePrice = cur;
}
void setPrice(double price) {
this->curPrice = price;
this->change();
}
double getPrice() {
return this->curPrice;
}
void add(Observer* observer) {
this->observers.push_back(observer);
}
void change() {
if (this->curPrice >= this->prePrice * (1 + 0.05)) {
update();
}
this->prePrice = this->curPrice;
}
void update() {
for (vector<Observer*>::iterator it = this->observers.begin(); it != this->observers.end(); it++) {
(*it)->notify();
}
}
private:
vector<Observer*> observers;
double curPrice;
double prePrice;
};
void O();
#include"Observer.h"
void O() {
double cur = 1.00;
Stock* s = new ConcreteStock(cur);
Observer* observer1 = new ConcreteObserver();
Observer* observer2 = new ConcreteObserver();
Observer* observer3 = new ConcreteObserver();
s->add(observer1);
s->add(observer2);
s->add(observer3);
while (1) {
cout << "previous stock:" << cur << endl;
cout << "please input current stock:";
cin >> cur;
s->setPrice(cur);
cin.sync();
cin.clear();
cout << "==================================================" << endl;
}
}
运行结果:
3.4 观察者模式在主流框架中的应用
- QT中的信号和槽机制:Qt 中的信号和槽机制是一种观察者模式的实现。通过 connect() 函数,一个对象(信号发射者)可以将其信号连接到另一个对象(槽)的槽函数上。当信号发射者的状态发生变化时,它会发出信号,所有连接到该信号的槽函数都会被调用。
- Qt 的模型/视图架构:Qt 中的模型/视图架构也使用了观察者模式。例如,QAbstractItemModel 类作为数据模型,当数据发生变化时会发出信号通知视图(如 QTableView、QTreeView)更新界面。(还有Django中的MVC模式,其思想跟观察者模式挺相似的。)
- Java 的事件处理机制:Java 中的事件处理机制就是观察者模式的一种应用。例如,Swing GUI 应用程序中的按钮点击事件、文本框内容改变事件等,都可以通过注册监听器(观察者)来处理