zoukankan      html  css  js  c++  java
  • (一)观察者模式-C++实现

    观察者模式:

        定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都得到通知并被自动更新。

    它有四种角色:

    主题(Subject):一个接口,规定了具体主题需要实现的方法。

    观察者(Observer):也是一个接口,规定了具体观察者用来更新数据的方法。

    具体主题:实现主题接口的一个实例,比如本例中的“就业通知中心”;里面会维护一个具体观察者的集合。本文使用STL中的list。

    具体观察者:实现观察者的一个实例,会包含存放主题的引用或者指针。

    使用C++实现如下:

    包含5个文件,头文件两个:主题类(Subject.h)观察者类(Observer.h)

    源文件两个:主题类(Subject.cpp)观察者类(Observer.h)

    一个测试文件。

    //Subject.h

    #ifndef _SUBJECT_H_
    #define _SUBJECT_H_
    #include "Observer.h"
    #include <list>
    #include <string>
    using namespace std;
    class Observer;//注意C++中虽然包含了头文件这里也需要声明
    typedef list<Observer*> myList;
    
    class Subject{
    public:
    	Subject(){}
    	virtual ~Subject(){}
    	virtual void addObserver(Observer* o) = 0;
    	virtual void deleteObserver(Observer* o) = 0;
    	virtual void notifyObservers() = 0;
    
    };
    
    class SeekJobCenter : public Subject
    {
    public:
    	SeekJobCenter();
    	~SeekJobCenter(){}
    	void addObserver(Observer* o);
    	void deleteObserver(Observer* o);
    
    	void notifyObservers();
    	void giveNewMessage(string str);
    
    private:
    	string mess;
    	bool changed;
    	myList personList;
    
    };
    
    
    #endif
    

    //Subject.cpp

    //具体的主题
    #include "stdafx.h"
    #include "Subject.h"
    #include "Observer.h"
    #include <list>
    
    SeekJobCenter::SeekJobCenter()
    {
    	mess = "";
    	changed = false;
    }
    void SeekJobCenter::addObserver(Observer* o)
    {
    	list<Observer*>::iterator it;
    	//判断原始维护的list中是否存在添加的对象
    	it = find(personList.begin(), personList.end(), o);
    	if (it == personList.end())//不存在
    	{
    		personList.push_back(o);
    	}
    	return;
    }
    
    void SeekJobCenter::deleteObserver(Observer* o)
    {
    	list<Observer*>::iterator it;
    	it = find(personList.begin(), personList.end(), o);
    	if (it != personList.end())//存在
    	{
    		personList.remove(*it);
    		delete(*it);
    	}
    	return;
    }
    
    void SeekJobCenter::notifyObservers()
    {
    	list<Observer*>::iterator it;
    	if (changed)
    	{
    		for (it = personList.begin(); it != personList.end(); ++it)
    		{
    			(*it)->hearTelephone(mess);
    		}
    		changed = false;
    	}
    	return;
    }
    
    void SeekJobCenter::giveNewMessage(string str)
    {
    	if (0 == strcmp(str.c_str(), mess.c_str()))
    	{
    		changed = false;
    	}
    	else
    	{
    		mess = str;
    		changed = true;
    	}
    	return;
    }
    

    //Observer.h

    #ifndef _OBSERVER_H_
    #define _OBSERVER_H_
    #include <string>
    #include <iostream>
    #include <list>
    #include "Subject.h"
    using namespace std;
    class Subject;
    /*
    观察者基类
    */
    class Observer
    {
    public:
    	Observer(){};
    	virtual ~Observer(){};
    	virtual void hearTelephone(string heardMess) = 0;
    
    };
    
    class UniversityStudent : public Observer
    {
    public:
    	UniversityStudent(Subject* subject);
    	virtual ~UniversityStudent(){};
    	void hearTelephone(string heardMess);
    
    private:
    	Subject* subject;
    
    };
    
    class HaiGui : public Observer
    {
    public:
    	HaiGui(Subject *subject);
    	virtual ~HaiGui(){};
    	void hearTelephone(string heardMess);
    
    private:
    	Subject *subject;
    
    };
    
    
    #endif
    

    //Observer.cpp

     1 #include "stdafx.h"
     2 #include "Observer.h"
     3 #include "Subject.h"
     4 
     5 UniversityStudent::UniversityStudent(Subject* subject)
     6 {
     7     if (NULL != subject)
     8     {
     9         this->subject = subject;
    10     }
    11     else
    12     {
    13         return;
    14     }
    15 
    16     subject->addObserver(this);
    17 }
    18 void UniversityStudent::hearTelephone(string heardMess)
    19 {
    20     std::cout << "I am a university student" << std::endl;
    21     std::cout << "I hear message is " << heardMess << std::endl;
    22     return;
    23 }
    24 
    25 HaiGui::HaiGui(Subject* subject)
    26 {
    27     if (NULL != subject)
    28     {
    29         this->subject = subject;
    30     }
    31     else
    32     {
    33         return;
    34     }
    35     subject->addObserver(this);
    36 }
    37 
    38 void HaiGui::hearTelephone(string heardMess)
    39 {
    40     std::cout << "I am a HaiGui" << std::endl;
    41     std::cout << "I hear message is " ;
    42     cout << heardMess << endl;
    43     return;
    44 }
    View Code

    最后一个测试的文件:

    #include "stdafx.h"
    #include "Observer.h"
    #include "Subject.h"
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	SeekJobCenter *center = new SeekJobCenter();
    	UniversityStudent *chengchaolee = new UniversityStudent(center);
    	HaiGui *haigui = new HaiGui(center);
    	center->giveNewMessage("I need a cook");
    	center->notifyObservers();
    	center->giveNewMessage("I need a xxxx");
    	center->notifyObservers();
    
    	delete center;
    	delete chengchaolee;
    	delete haigui;
    	return 0;
    }
    

        定义两个具体的观察者,并且以具体主题作为参数,代表它观察的对象,然后当主题推送数据时,观察者就会收到消息,即“推数据”的方式,当然还有一种观察者模式采用的是拉数据,即由观察者自己定义需要什么数据,主题在notify的时候并不传递参数而是在观察者更新数据时,将Subject向下转换为具体Subject,从而获取其中相应的数据,这种方式叫做“拉数据”。

        值得注意的是,C++在实现的时候,采用list存储具体观察者,需要使用list<Observer*>类型,即使用指针。不然会编译不通过,因为Observer是虚基类,无法实例化。

  • 相关阅读:
    渗透利器-kali工具 (第二章-4) 信息收集之目录扫描
    渗透利器-kali工具 (第二章-3) 信息收集之子域名扫描 -Sublist3
    渗透利器-kali工具 (第二章-2) 信息收集之端口扫描-NMAP
    渗透利器-kali工具 (第二章-1) 渗透测试流程以及信息收集总纲
    (4)top详解 (每周一个linux命令系列)
    (3)lscpu详解 (每周一个linux命令系列)
    (2)free详解 (每周一个linux命令系列)
    每周一个linux命令之---uptime详解
    使用python制作时间戳转换工具
    PSR规范0-4整理
  • 原文地址:https://www.cnblogs.com/leewhite/p/6027421.html
Copyright © 2011-2022 走看看