前言
观察者模式定义对象间的一种一对多的依赖关系,当一个对象(subject,被观察者)的状态发生变化的时候,所有依赖于它的对象(observer,观察者)都会得到通知并自动更新。
其中subject类必须的成员:
1,vector<Observer*> m_observers;
2,add_observer(Observer* observer);
3,remove_observer(Observer* observer);
4,notify();
Observer类必须的成员:
1,get_notify();
本例背景阐述
一个算法常常需要包含多个步骤,而在调试算法的时候,算法工程师需要对每一个步骤进行输出,确保每一个步骤的结果都符合预期。本例以医学图像分割为例对观察者模式进行分析,其中算法的实现过程为Subject,输出中间过程的类为Observer。
本例定义的图像分割包含4个步骤:
1,原始图像重采样到算法需要的分辨率;
2,对图像进行归一化;
3,采用大津阈值对图像进分割;
4,将分割结果重采样回原始分辨率。
代码实现过程
头文件代码段和定义Observer 和Subject 两个类。
#include <iostream>
#include <vector>
using namespace std;
class Observer;
class Subject;
观察者模块,先定义了抽象接口类和纯虚函数,然后通过继承实现Debug类并重写纯虚函数。
#pragma region 观察者模块
class Observer
{
public:
virtual void update(const char* msg) =0;
virtual ~Observer(){};
};
class Debug : public Observer
{
public:
void update(const char* msg);
virtual ~Debug(){};
};
void Debug::update(const char* msg)
{
cout<<"Debug result:"<<msg<<endl;
}
#pragma endregion
被观察者模块,先定义算法的抽象接口类,然后通过继承实现Segment类。
#pragma region 被观察者模块
class Subject
{
public:
virtual void add_observer(Observer* observer) = 0;
virtual void remove_observer(Observer* observer) = 0;
virtual void notify(const char* msg) = 0;
virtual ~Subject(){};
};
class Segment: public Subject
{
public:
void add_observer(Observer* observer);
void remove_observer(Observer* observer);
void notify(const char* msg);
void run_alg();
private:
void resample_image(){
cout<<"重采样完成."<<endl;
}
void normalization(){
cout<<"归一化完成."<<endl;
}
void otsu_threshold(){
cout<<"大津阈值处理完成."<<endl;
}
void resample_ref(){
cout<<"重采样回原始分辨率完成."<<endl;
}
vector<Observer*> m_observers;
};
void Segment::add_observer(Observer* observer)
{
auto it = find(m_observers.cbegin(), m_observers.cend(), observer);
if (it != m_observers.cend()){
cout<<"add_observer faild, becouse the observer exist."<<endl;
}
else{
m_observers.push_back(observer);
}
}
void Segment::remove_observer(Observer* observer)
{
auto it = find(m_observers.cbegin(), m_observers.cend(), observer);
if(it != m_observers.cend()){
m_observers.erase(it);
}
else{
cout <<"observer not in list, cannot remove it."<<endl;
}
}
void Segment::notify(const char* msg)
{
for(const auto t_elem : m_observers){
t_elem->update(msg);
}
}
void Segment::run_alg()
{
resample_image();
notify("重采样结果正确");
normalization();
notify("归一化结果正确");
otsu_threshold();
notify("大津阈值结果正确");
resample_ref();
notify("重采样回原始分辨率正确");
}
#pragma endregion
测试main函数代码
int main(int argc, char const *argv[])
{
unique_ptr<Segment> segment_ptr(new Segment());
unique_ptr<Debug> debug_ptr_01(new Debug());
unique_ptr<Debug> debug_ptr_02(new Debug());
unique_ptr<Debug> debug_ptr_03(new Debug());
// 实际应用中,只需要修改这里的代码就能控制是否输出中间过程
segment_ptr->add_observer(debug_ptr_01.get());
segment_ptr->add_observer(debug_ptr_02.get());
segment_ptr->add_observer(debug_ptr_01.get()); // 测试重复添加观察者
segment_ptr->remove_observer(debug_ptr_03.get()); // 测试不存在的观察者是否可以移除
segment_ptr->run_alg();
cout<< "\n\n移除观察者后的运行效果测试." << endl;
segment_ptr->remove_observer(debug_ptr_01.get());
segment_ptr->remove_observer(debug_ptr_02.get());
segment_ptr->run_alg();
return 0;
}
输出结果如下:
$ ./observer.exe
add_observer faild, becouse the observer exist.
observer not in list, cannot remove it.
重采样完成.
Debug result:重采样结果正确
Debug result:重采样结果正确
归一化完成.
Debug result:归一化结果正确
Debug result:归一化结果正确
大津阈值处理完成.
Debug result:大津阈值结果正确
Debug result:大津阈值结果正确
重采样回原始分辨率完成.
Debug result:重采样回原始分辨率正确
Debug result:重采样回原始分辨率正确
移除观察者后的运行效果测试.
重采样完成.
归一化完成.
大津阈值处理完成.
重采样回原始分辨率完成.