观察者模式
在软件架构中,我们需要对某些对象建立一种“通知依赖的关系”:一个对象的状态发生改变,所有的依赖对象都需要得到通知。
如果这样的关系过于紧密,将使得软件不能很好的抵御变化;使用观察者模式,可以将这种依赖关系弱化,形成一种稳定的依赖关系,从而实现软件体系结构的松耦合。
使用师生关系进行举例策略模式的类图关系如下:
teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <list>
#include <memory>
class Student;
using Student_ptr = std::shared_ptr<Student>;
//////////////////////////////////////////////////////////////////////////
/// \brief The Teacher class
/// 观察者模式
/// 在软件架构中,我们需要对某些对象建立一种“通知依赖的关系”:
/// 一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都需要得到通知。
/// 如果这样的关系过于紧密,将使软件不能很好的抵御变化;使用观察者模式,可以将这种
/// 依赖关系弱化,形成一种稳定的依赖关系,从而实现 软件体系结构的松耦合。
/// Teacher作为目标对象的基类,可以根据不同的子类进行扩展目标对象;而Student作为
/// 观察者对象的基类,也可以根据不同的子类进行观察者的扩展。
//////////////////////////////////////////////////////////////////////////
class Teacher
{
public:
Teacher();
virtual ~Teacher();
virtual void takeAClass() = 0;
void attach(Student_ptr student);//添加观察者
void detach(Student_ptr student);
protected:
void notify();//通知所有的观察者
private:
std::list<Student_ptr > m_list;
};
////////////////////////////////////////////////////////////
class TeacherA : public Teacher
{
public:
TeacherA();
virtual ~TeacherA();
virtual void takeAClass();//上课(在这里边进行通知)
};
////////////////////////////////////////////////////////////
class TeacherB : public Teacher
{
public:
TeacherB();
virtual ~TeacherB();
virtual void takeAClass();//上课(在这里边进行通知)
};
#endif // TEACHER_H
teacher.cpp
#include "teacher.h"
#include "student.h"
#include <iostream>
Teacher::Teacher() {
std::cout << "Teacher::Teacher" << std::endl;
}
Teacher::~Teacher() {
std::cout << "Teacher::~Teacher" << std::endl;
m_list.clear();
}
void Teacher::attach(Student_ptr student) {
if(student) m_list.push_back(student);
}
void Teacher::detach(Student_ptr student) {
if(student) {
m_list.remove(student);
}
}
void Teacher::notify() {
for(Student_ptr student : m_list) {
if(student) student->doSomething();
}
}
///////////////////////////////////////////////////////////////////////////
TeacherA::TeacherA()
: Teacher() {
std::cout << "TeacherA::TeacherA" << std::endl;
}
TeacherA::~TeacherA() {
std::cout << "TeacherA::~TeacherA" << std::endl;
}
void TeacherA::takeAClass() {
std::cout << "TeacherA::takeAClass" << std::endl;
notify();
}
///////////////////////////////////////////////////////////////////////////
TeacherB::TeacherB()
: Teacher() {
std::cout << "TeacherB::TeacherB" << std::endl;
}
TeacherB::~TeacherB() {
std::cout << "TeacherB::~TeacherB" << std::endl;
}
void TeacherB::takeAClass() {
std::cout << "TeacherB::takeAClass" << std::endl;
notify();
}
student.h
#ifndef STUDENT_H
#define STUDENT_H
class Student
{
public:
Student();
virtual ~Student();
virtual void doSomething();
};
//////////////////////////////////////////////////////////////
class StudentA : public Student
{
public:
StudentA();
virtual ~StudentA();
virtual void doSomething();
};
//////////////////////////////////////////////////////////////
class StudentB : public Student
{
public:
StudentB();
virtual ~StudentB();
virtual void doSomething();
};
#endif // STUDENT_H
student.cpp
#include "student.h"
#include <iostream>
Student::Student() {
std::cout << "Student::Student" << std::endl;
}
Student::~Student() {
std::cout << "Student::~Student" << std::endl;
}
void Student::doSomething() {
std::cout << "Student::doSomething" << std::endl;
}
//////////////////////////////////////////////////////////////////////////
StudentA::StudentA()
: Student() {
std::cout << "StudentA::StudentA" << std::endl;
}
StudentA::~StudentA() {
std::cout << "StudentA::~StudentA" << std::endl;
}
void StudentA::doSomething() {
std::cout << "StudentA::doSomething" << std::endl;
}
/////////////////////////////////////////////////////////////////////////
StudentB::StudentB()
: Student() {
std::cout << "StudentB::StudentB" << std::endl;
}
StudentB::~StudentB() {
std::cout << "StudentB::~StudentB" << std::endl;
}
void StudentB::doSomething() {
std::cout << "StudentB::doSomething" << std::endl;
}
main.cpp
#include <QCoreApplication>
#include "teacher.h"
#include "student.h"
#include <memory>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::cout << "**************************************************" << std::endl;
{
/////////////////////////////////////////////////////////////////////////
/////假设目前需求只有StudentA类型的任务
std::shared_ptr<Student> studentA1 = std::make_shared<StudentA>();
std::shared_ptr<Student> studentA2 = std::make_shared<StudentA>();
std::shared_ptr<Teacher> teacherA = std::make_shared<TeacherA>();
teacherA->attach(studentA1);
teacherA->attach(studentA2);
teacherA->takeAClass();
}
std::cout << "**************************************************" << std::endl;
{
/////////////////////////////////////////////////////////////////////////
/////新增需求StudentB类型的任务
std::shared_ptr<Student> studentB1 = std::make_shared<StudentB>();
std::shared_ptr<Student> studentB2 = std::make_shared<StudentB>();
std::shared_ptr<Teacher> teacherA1 = std::make_shared<TeacherA>();
teacherA1->attach(studentB1);
teacherA1->attach(studentB2);
teacherA1->takeAClass();
}
std::cout << "**************************************************" << std::endl;
{
/////////////////////////////////////////////////////////////////////////
/////新增需求StudentA、StudentB类型的任务等
std::shared_ptr<Student> studentA11 = std::make_shared<StudentA>();
std::shared_ptr<Student> studentB11 = std::make_shared<StudentB>();
std::shared_ptr<Teacher> teacherB = std::make_shared<TeacherB>();
teacherB->attach(studentA11);
teacherB->attach(studentB11);
teacherB->takeAClass();
}
std::cout << "**************************************************" << std::endl;
return a.exec();
}
将观察者和被观察者分别抽象后,能够适应更多的扩展。