动机(Motivation)
-
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对 象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
-
使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
模式定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。 ——《 设计模式》 GoF
要点总结
-
使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
-
目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。即Notify会自动根据多态来调用相应的观察者
-
观察者自己决定是否需要订阅通知,目标对象对此一无所知。即是否需要attach新的观察者
-
Observer模式是基于事件的UI框架中常用的设计模式,也是MVC模式的一个重要组成部分。
-
它是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
非观察者模式
缺点:当需要增加新的观察者时,需修改具体的Subject中的代码,违背了开闭原则。并且其也违背了依赖倒置原则,高层模块不应该依赖于底层模块,两者都应该依赖抽象。
#include <iostream>
//观察者1
class XiaoMing
{
public:
void DoSomething()
{
std::cout << "老师来了,停止打闹" << std::endl;
}
};
//观察者2
class XiaoQiang
{
public:
void DoSomething()
{
std::cout << "老师来了,可以问问题了" << std::endl;
}
};
//具体目标
class Teacher
{
public:
//通知
void Come()
{
qiang.DoSomething();
ming.DoSomething();
}
private:
XiaoQiang qiang;
XiaoMing ming;
};
int main()
{
Teacher teacher;
teacher.Come();
return 0;
}
观察者模式
#include <iostream>
//#include<algorithm>
#include <list>
//抽象类,观察者接口,收到通知用来更新观察者。
class IObserver
{
public:
virtual void DoSomething() = 0; //Update接口
virtual ~IObserver()
{
std::cout << "~IObserver"<<std::endl;
}
};
//观察者1
class XiaoMing : public IObserver
{
public:
void DoSomething()
{
std::cout << "老师来了,停止打闹" << std::endl;
}
};
//观察者2
class XiaoQiang : public IObserver
{
public:
void DoSomething()
{
std::cout << "老师来了,可以问问题了" << std::endl;
}
};
//目标接口
class ISubject
{
public:
virtual void Attach(IObserver *observer) = 0;
virtual void Detach(IObserver *observer) = 0;
virtual void Notify() = 0;
virtual ~ISubject(){}
};
//具体目标
class Teacher : public ISubject
{
private:
std::list<IObserver *> listObserver;//多个观察者,并且必须得是指针类型(多态)
public:
//订阅,增加观察者
void Attach(IObserver *observer)
{
listObserver.push_back(observer);
}
//删除
void Detach(IObserver *observer)
{
auto itor = std::find(listObserver.begin(), listObserver.end(), observer);
listObserver.erase(itor);
}
//通知
void Notify()
{
for (auto observer : listObserver)
{
observer->DoSomething();
}
}
};
int main()
{
Teacher teacher;
IObserver *observer1 = new XiaoMing();
IObserver *observer2 = new XiaoQiang();
teacher.Attach(observer1);
teacher.Attach(observer2);
teacher.Notify();
teacher.Detach(observer2);
teacher.Notify();
delete observer1;
delete observer2;
observer1 = nullptr;
observer2 = nullptr;
return 0;
}
智能指针优化改进
#include <iostream>
//#include<algorithm>
#include <list>
//抽象类,观察者接口,收到通知用来更新观察者。
class IObserver
{
public:
virtual void DoSomething() = 0; //Update接口
virtual ~IObserver()
{
std::cout << "~IObserver"<<std::endl;
}
};
//观察者1
class XiaoMing : public IObserver
{
public:
void DoSomething()
{
std::cout << "老师来了,停止打闹" << std::endl;
}
};
//观察者2
class XiaoQiang : public IObserver
{
public:
void DoSomething()
{
std::cout << "老师来了,可以问问题了" << std::endl;
}
};
//智能指针
using IObserverPtr = std::shared_ptr< IObserver>;
//目标接口
class ISubject
{
public:
virtual void Attach(IObserverPtr observer) = 0;
virtual void Detach(IObserverPtr observer) = 0;
virtual void Notify() = 0;
virtual ~ISubject(){}
};
//具体目标
class Teacher : public ISubject
{
private:
std::list<IObserverPtr> listObserver;//多个观察者,并且必须得是指针类型(多态)
public:
//订阅,增加观察者
void Attach(IObserverPtr observer)
{
listObserver.push_back(observer);
}
//删除
void Detach(IObserverPtr observer)
{
auto itor = std::find(listObserver.begin(), listObserver.end(), observer);
listObserver.erase(itor);
}
//通知
void Notify()
{
for (auto observer : listObserver)
{
observer->DoSomething();
}
}
};
int main()
{
Teacher teacher;
IObserverPtr observer1 = std::make_shared<XiaoMing>();
IObserverPtr observer2 = std::make_shared <XiaoQiang>();
teacher.Attach(observer1);
teacher.Attach(observer2);
teacher.Notify();
teacher.Detach(observer2);
teacher.Notify();
return 0;
}