1.动机
(1)在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
(2)使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
2.模式定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
——《设计模式》GoF
3.结构(Structure)
4.要点总结
(1)使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
(2)目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
(3)观察者自己决定是否需要订阅通知,目标对象对此一无所知。
(4)Observer模式是基于事件的UI框架中非常常用的设计模式,也是
MVC模式的一个重要组成部分。
5.示例
(1)未使用观察者模式
MainForm.cpp
class MainForm : public Form
{
TextBox* txtFilePath;
TextBox* txtFileNumber;
ProgressBar* progressBar;
public:
void Button1_Click(){
string filePath = txtFilePath->getText();
int number = atoi(txtFileNumber->getText().c_str());
FileSplitter splitter(filePath, number, progressBar);
splitter.split();
}
};
FileSpiliter.cpp
class FileSplitter
{
string m_filePath;
int m_fileNumber;
ProgressBar* m_progressBar;
public:
FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar) :
m_filePath(filePath),
m_fileNumber(fileNumber),
m_progressBar(progressBar){
}
void split(){
//1.读取大文件
//2.分批次向小文件中写入
for (int i = 0; i < m_fileNumber; i++){
//...
float progressValue = m_fileNumber;
progressValue = (i + 1) / progressValue;
m_progressBar->setValue(progressValue);
}
}
};
(2)使用观察者模式
将控件类,和变化类分离。
IProgress相当于Observer类,MainForm,ConsoleNotify相当于ConcreteObserver。
FileSplitter相当于ConcreteSubject。
MainForm.cpp
class MainForm : public Form, public IProgress
{
TextBox* txtFilePath;
TextBox* txtFileNumber;
ProgressBar* progressBar;
public:
void Button1_Click(){
string filePath = txtFilePath->getText();
int number = atoi(txtFileNumber->getText().c_str());
ConsoleNotifier cn;
FileSplitter splitter(filePath, number);
splitter.addIProgress(this); //订阅通知
splitter.addIProgress(&cn); //订阅通知
splitter.split();
splitter.removeIProgress(this);
}
virtual void DoProgress(float value){
progressBar->setValue(value);
}
};
class ConsoleNotifier : public IProgress {
public:
virtual void DoProgress(float value){
cout << ".";
}
};
FileSpliter.cpp
class IProgress{
public:
virtual void DoProgress(float value)=0;
virtual ~IProgress(){}
};
class FileSplitter
{
string m_filePath;
int m_fileNumber;
List<IProgress*> m_iprogressList; // 抽象通知机制,支持多个观察者
public:
FileSplitter(const string& filePath, int fileNumber) :
m_filePath(filePath),
m_fileNumber(fileNumber){
}
void split(){
//1.读取大文件
//2.分批次向小文件中写入
for (int i = 0; i < m_fileNumber; i++){
//...
float progressValue = m_fileNumber;
progressValue = (i + 1) / progressValue;
onProgress(progressValue);//发送通知
}
}
void addIProgress(IProgress* iprogress){
m_iprogressList.push_back(iprogress);
}
void removeIProgress(IProgress* iprogress){
m_iprogressList.remove(iprogress);
}
protected:
virtual void onProgress(float value){
List<IProgress*>::iterator itor=m_iprogressList.begin();
while (itor != m_iprogressList.end() )
(*itor)->DoProgress(value); //更新进度条
itor++;
}
}
};
#include <algorithm>
#include <vector>
#include <stdio.h>
#include "../Mutex.h"
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
class Observable;
class Observer : public boost::enable_shared_from_this<Observer>
{
public:
virtual ~Observer();
virtual void update() = 0;
void observe(Observable* s);
protected:
Observable* subject_;
};
class Observable
{
public:
void register_(boost::weak_ptr<Observer> x);
// void unregister(boost::weak_ptr<Observer> x);
void notifyObservers()
{
muduo::MutexLockGuard lock(mutex_);
Iterator it = observers_.begin();
while (it != observers_.end())
{
boost::shared_ptr<Observer> obj(it->lock());
if (obj)
{
obj->update();
++it;
}
else
{
printf("notifyObservers() erase\n");
it = observers_.erase(it);
}
}
}
private:
mutable muduo::MutexLock mutex_;
std::vector<boost::weak_ptr<Observer> > observers_;
typedef std::vector<boost::weak_ptr<Observer> >::iterator Iterator;
};
Observer::~Observer()
{
// subject_->unregister(this);
}
void Observer::observe(Observable* s)
{
s->register_(shared_from_this());
subject_ = s;
}
void Observable::register_(boost::weak_ptr<Observer> x)
{
observers_.push_back(x);
}
//void Observable::unregister(boost::weak_ptr<Observer> x)
//{
// Iterator it = std::find(observers_.begin(), observers_.end(), x);
// observers_.erase(it);
//}
// ---------------------
class Foo : public Observer
{
virtual void update()
{
printf("Foo::update() %p\n", this);
}
};
int main()
{
Observable subject;
{
boost::shared_ptr<Foo> p(new Foo);
p->observe(&subject);
subject.notifyObservers();
}
subject.notifyObservers();
}
#include <algorithm>
#include <vector>
#include <stdio.h>
class Observable;
class Observer
{
public:
virtual ~Observer();
virtual void update() = 0;
void observe(Observable* s);
protected:
Observable* subject_;
};
class Observable
{
public:
void register_(Observer* x);
void unregister(Observer* x);
void notifyObservers()
{
for (size_t i = 0; i < observers_.size(); ++i)
{
Observer* x = observers_[i];
if (x) {
x->update(); // (3)
}
}
}
private:
std::vector<Observer*> observers_;
};
Observer::~Observer()
{
subject_->unregister(this);
}
void Observer::observe(Observable* s)
{
s->register_(this);
subject_ = s;
}
void Observable::register_(Observer* x)
{
observers_.push_back(x);
}
void Observable::unregister(Observer* x)
{
std::vector<Observer*>::iterator it = std::find(observers_.begin(), observers_.end(), x);
if (it != observers_.end())
{
std::swap(*it, observers_.back());
observers_.pop_back();
}
}
// ---------------------
class Foo : public Observer
{
virtual void update()
{
printf("Foo::update() %p\n", this);
}
};
int main()
{
Foo* p = new Foo;
Observable subject;
p->observe(&subject);
subject.notifyObservers();
delete p;
subject.notifyObservers();
}
ObservableSubject是主题,里面有两种event进行订阅主题,Observer的函数onSubjectModified,和modified分别订阅了主题
#include <cstddef>
import <map>;
import <functional>;
import <iostream>;
using namespace std;
using EventHandle = size_t;
template <typename... Args>
class Event
{
public:
virtual ~Event() = default; // Always a virtual destructor!
// Adds an observer. Returns an EventHandle to unregister the observer.
[[nodiscard]] EventHandle operator+=(function<void(Args...)> observer)
{
auto number{ ++m_counter };
m_observers[number] = observer;
return number;
}
// Unregisters the observer pointed to by the given handle.
Event& operator-=(EventHandle handle)
{
m_observers.erase(handle);
return *this;
}
// Raise event: notifies all registered observers.
void raise(Args... args)
{
for (auto& observer : m_observers) {
(observer.second)(args...);
}
}
private:
size_t m_counter{ 0 };
map<EventHandle, function<void(Args...)>> m_observers;
};
class ObservableSubject
{
public:
auto& getEventDataModified() { return m_eventDataModified; }
auto& getEventDataDeleted() { return m_eventDataDeleted; }
void modifyData()
{
// ...
getEventDataModified().raise(1, 2.3);
}
void deleteData()
{
// ...
getEventDataDeleted().raise();
}
public:
Event<int, double> m_eventDataModified;
Event<> m_eventDataDeleted;
};
void modified(int, double)
{
cout << "modified" << endl;
}
class Observer
{
public:
Observer(ObservableSubject& subject) : m_subject{ subject }
{
m_subjectModifiedHandle = m_subject.getEventDataModified() +=
[this](int i, double d) { onSubjectModified(i, d); };
}
virtual ~Observer()
{
m_subject.getEventDataModified() -= m_subjectModifiedHandle;
}
private:
void onSubjectModified(int, double)
{
cout << "Observer::onSubjectModified()" << endl;
}
ObservableSubject& m_subject;
EventHandle m_subjectModifiedHandle;
};
int main()
{
ObservableSubject subject;
auto handleModified{ subject.getEventDataModified() += modified };
auto handleDeleted{ subject.getEventDataDeleted() += [] { cout << "deleted" << endl; } };
Observer observer{ subject };
subject.modifyData();
subject.deleteData();
cout << endl;
subject.getEventDataModified() -= handleModified;
subject.modifyData();
subject.deleteData();
}