一、观察者模式简介
1.定义
观察者模式:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并自动更新。
2.意义
此设计模式最重要的作用就是解耦,将观察者与被观察者解耦,使得他们之间的依赖性更小。
优点
- 观察者模式可以实现表现层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色
- 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
- 观察者模式支持广播通信。
- 观察者模式符合“开闭原则”的要求。
缺点
- 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
观察者模式适用环境
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象,可以使用观察者模式创建一种链式触发机制。
3.UML图
二、观察者模式实例
在本例中,观察者是程序员,被观察者是各个公司。
程序员又具体继承出CPP程序员,JAVA程序员,PHP程序员。公司继承出阿里巴巴和腾讯。
程序员在各个公司中注册。
公司发布不同的职位,并通知在该公司注册的程序员。
程序员得到通知后,根据当前职位和自身需求,决定是否要投递简历。
#include<iostream>
#include <algorithm>
#include <string>
#include <list>
#include <memory>
using namespace std;
enum class Position
{
CPP,
JAVA,
PHP,
C_Sharp,
Python
};
class Engineer
{
public:
Engineer(const string &name) :name_(name) {};
virtual void update(Position position) = 0;
protected:
string name_;
};
class CppEngineer:public Engineer
{
public:
CppEngineer(const string &name) :Engineer(name) {};
virtual void update(Position position)override
{
if (position == Position::CPP)
{
cout << name_ << " 投递简历!" << endl;
}
}
};
class PHPEngineer :public Engineer
{
public:
PHPEngineer(const string&name) :Engineer(name) {};
virtual void update(Position position)override
{
if (position == Position::PHP)
{
cout << name_ << " 投递简历!" << endl;
}
}
};
class JAVAEngineer :public Engineer
{
public:
JAVAEngineer(const string&name) :Engineer(name) {};
virtual void update(Position position)override
{
if (position == Position::JAVA)
{
cout << name_ << " 投递简历!" << endl;
}
}
};
class Alibaba
{
public:
void Recruit(Position position) //招聘某种职位
{
Notify(position);
}
void AddEngineer(shared_ptr<Engineer> engineer)
{
engineer_list.push_back(engineer);
}
private:
list<shared_ptr<Engineer>> engineer_list;
void Notify(Position position) //通知
{
for (const auto &engineer : engineer_list)
{
engineer->update(position);
}
}
};
int main()
{
Alibaba ali;
ali.AddEngineer(make_shared<CppEngineer>("C++程序员"));
ali.AddEngineer(make_shared<JAVAEngineer>("Java程序员"));
ali.AddEngineer(make_shared<PHPEngineer>("PHP程序员"));
ali.Recruit(Position::CPP);
ali.Recruit(Position::Python);
ali.Recruit(Position::C_Sharp);
ali.Recruit(Position::PHP);
}
运行结果如下: