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这两个类需要相互引用,总之就是两个类如果要相互引用的话像我上面这样写就对了。
两个类相互引用,不管哪个类在前面,都会出现有一个类未定义的情况,所以可以提前声明一个类,而类的声明就是提前告诉编译器,所要引用的是个类,但此时后面的那个类还没有定义,因此无法给对象分配确定的内存空间,因此只能使用类指针,不能引用实体对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值