C++实现设计模式——观察者模式

关于观察者模式,对它的认知依旧是起源于菜鸟教程的设计模式篇章,里面解释的很到位。
这里简单介绍一句,当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。详细介绍戳该链接——菜鸟教程~观察者模式

本文分享一个老师布置作业的例子

感觉这个例子完美诠释了观察者模式,学生作为观察者,观察者模式的设计可以让老师在布置作业后,自动通知到每个选了该老师课的学生,话不多说,先上个UML图。
这里写图片描述

然后再上个代码吧
student.h
#ifndef _STUDENT_
#define _STUDENT_

#include "iostream"
#include "string"
#include "list"
#include "teacher.h"

using namespace std;

class teacher;

class student
{
protected:
    string m_homework;
public:
    student(){}
    virtual string get_content() = 0;   //获取作业内容
    virtual void update_content() = 0;  //更新作业内容
};

class programming_stu:public student
{
private:
    string m_name;         //学生名字
    teacher *m_t;          //该学生的老师
public:
    programming_stu(string name, teacher *t):m_name(name),m_t(t){}
    ~programming_stu();
    string get_content();
    void update_content();
};

#endif
student.cpp
#include "student.h"
#include "teacher.h"
#include "iostream"
#include "string"
#include "list"

using namespace std;

string programming_stu::get_content()
{
    return m_homework;
}

void programming_stu::update_content()
{
    m_homework = m_name + ":" + m_t->get_content();
    return;
}
teacher.h
#ifndef _TEACHER_
#define _TEACHER_

#include "iostream"
#include "string"
#include "student.h"
#include "list"

using namespace std;

class student;

class teacher
{
private:
    list<student*> m_observers;   //记录老师的所有学生
protected:
    string m_homework;  //家庭作业内容
public:
    virtual void set_content(string content) = 0;
    virtual string get_content() = 0;
    void add_stu(student *stu);
    void dec_stu(student *stu);
    void notify_stu();
};

class programming_teacher:public teacher
{
private:
    string m_name;
public:
    programming_teacher(string str_name):m_name(str_name){}
    ~programming_teacher();
    void set_content(string str_homework);
    string get_content();
};

#endif
teacher.cpp
#include "student.h"
#include "teacher.h"
#include "iostream"
#include "string"
#include "list"

using namespace std;

void teacher::add_stu(student *stu)
{
    m_observers.push_back(stu);
}

void teacher::dec_stu(student *stu)
{
    m_observers.remove(stu);
}

void teacher::notify_stu()
{
    list<student*>::iterator it_stu;
    for (it_stu=m_observers.begin(); it_stu!=m_observers.end(); it_stu++)
    {
        (*it_stu)->update_content();
    }
}

void programming_teacher::set_content(string str_homework)
{
    m_homework = "The assignment " + m_name + " arranged is " + str_homework;
    notify_stu();
}

string programming_teacher::get_content()
{
    return m_homework;
}
observers_mode.cpp
#include "teacher.h"
#include "student.h"
#include "iostream"
#include "string"

using namespace std;

int main(int argc, char const *argv[])
{
    teacher *lzl = new programming_teacher("lzl");
    student *hk = new programming_stu("hk", lzl);
    student *gg = new programming_stu("gg", lzl);
    lzl->add_stu(hk);
    lzl->add_stu(gg);
    lzl->set_content("learn c++");
    cout << hk->get_content() << endl;
    lzl->dec_stu(hk);
    lzl->set_content("learn linux");
    cout << gg->get_content() << endl;
    cout << hk->get_content() << endl;

    if (lzl != NULL)
    {
        delete lzl;
        lzl = NULL;
    }
    if (hk != NULL)
    {
        delete hk;
        hk = NULL;
    }
    if (gg != NULL)
    {
        delete gg;
        gg = NULL;
    }
    return 0;
}

输出结果

这里写图片描述

最后分享一个C++小知识

写这个demo的时候还真是各种问题齐飞呀,一开始写完编译的时候各种未定义报错。原因是student和teacher这两个类需要相互引用,总之就是两个类如果要相互引用的话像我上面这样写就对了。
两个类相互引用,不管哪个类在前面,都会出现有一个类未定义的情况,所以可以提前声明一个类,而类的声明就是提前告诉编译器,所要引用的是个类,但此时后面的那个类还没有定义,因此无法给对象分配确定的内存空间,因此只能使用类指针,不能引用实体对象。

猜你喜欢

转载自blog.csdn.net/LonelyGambler/article/details/81159990