C++中Observer模式实现中的循环引用



我尝试使用Observer模式代码,该代码在https://sourcemaking.com/design_patterns/observer/cpp/3

观察员.h

#ifndef OBSERVER_H_
#define OBSERVER_H_
namespace my {
class Subject;
//template <class T>
class Observer {
    Subject*model;
    int denom;
    public:
        Observer(Subject*mod, int div);
        virtual void update() = 0;
        virtual ~Observer();
    protected:
        Subject*getSubject();
        int getDivisor();
};
} /* namespace my */
#endif /* OBSERVER_H_ */

Observer.cpp

#include "Observer.h"
//#include "Subject.h"
namespace my {
Observer::Observer(Subject*mod, int div)
{
    model = mod;
    denom = div;
    // 4. Observers register themselves with the Subject
    model->attach(this);
}
Subject* Observer::getSubject()
{
    return model;
}
int Observer::getDivisor()
{
    return denom;
}
Observer::~Observer() {
    // TODO Auto-generated destructor stub
}
} /* namespace my */

DivObserver.h

#ifndef DIVOBSERVER_H_
#define DIVOBSERVER_H_
#include <iostream>
#include "Observer.h"
using namespace std;
namespace my {
class DivObserver : public Observer
{
    public:
        DivObserver(Subject*mod, int div);
        void update();
        virtual ~DivObserver();
};
} /* namespace my */
#endif /* DIVOBSERVER_H_ */

DivObserver.cpp

#include "DivObserver.h"
namespace my {
DivObserver::DivObserver(Subject*mod, int div): Observer(mod, div){
    // TODO Auto-generated constructor stub
}
void DivObserver::update()
{
    // 6. "Pull" information of interest
    int v = getSubject()->getVal(), d = getDivisor();
    cout << v << " div " << d << " is " << v / d << 'n';
}
DivObserver::~DivObserver() {
    // TODO Auto-generated destructor stub
}
} /* namespace my */

主题h

#ifndef SUBJECT_H_
#define SUBJECT_H_
#include<vector>
using namespace std;
namespace my {
//template <class T>
class Subject {
    vector <class Observer*> views; // 3. Coupled only to "interface"
    int value;
    public:
        Subject();
        virtual ~Subject();
        void attach(Observer*obs);
        void setVal(int val);
        int getVal();
        void notify();
};
} /* namespace my */
#endif /* SUBJECT_H_ */

主题.cpp

#include "Subject.h"
namespace my {
Subject::Subject() {
    // TODO Auto-generated constructor stub
}
void Subject::attach(Observer*obs)
{
    views.push_back(obs);
}
void Subject::setVal(int val)
{
    value = val;
    notify();
}
int Subject::getVal()
{
    return value;
}
void Subject::notify()
{
  // 5. Publisher broadcasts
  for (int i = 0; i < views.size(); i++)
    views[i]->update();
}
Subject::~Subject() {
    // TODO Auto-generated destructor stub
}
} /* namespace my */

Test.cc

#include <iostream>
#include <vector>
#include "Subject.h"
#include "DivObserver.h"
using namespace std;
using namespace my;
int main() {
  Subject subj;
  DivObserver divObs1(&subj, 4); // 7. Client configures the number and
  DivObserver divObs2(&subj, 3); //    type of Observers
  subj.setVal(14);
}

它抱怨循环引用。如果我插入Subject类;上面写着模棱两可的主题。请帮我解决这个问题。

解决此问题的最简单方法是在一个文件中声明和定义observer和observable。意思是

主题h

#ifndef SUBJECT_H_
#define SUBJECT_H_
#include<vector>
namespace my {
class Subject;
//template <class T>
class Observer {
    Subject*model;
    int denom;
    public:
        Observer(Subject*mod, int div);
        virtual void update() = 0;
        virtual ~Observer();
    protected:
        Subject*getSubject();
        int getDivisor();
};
//template <class T>
class Subject {
    std::vector <Observer*> views; // 3. Coupled only to "interface"
    int value;
    public:
        Subject();
        virtual ~Subject();
        void attach(Observer*obs);
        void setVal(int val);
        int getVal();
        void notify();
};

} /* namespace my */
#endif

主题.cpp

#include "Subject.h"
namespace my {
DivObserver::DivObserver(Subject*mod, int div): Observer(mod, div){
    // TODO Auto-generated constructor stub
}
void DivObserver::update()
{
    // 6. "Pull" information of interest
    int v = getSubject()->getVal(), d = getDivisor();
    cout << v << " div " << d << " is " << v / d << 'n';
}
DivObserver::~DivObserver() {
    // TODO Auto-generated destructor stub
}
Subject::Subject() {
    // TODO Auto-generated constructor stub
}
void Subject::attach(Observer*obs)
{
    views.push_back(obs);
}
void Subject::setVal(int val)
{
    value = val;
    notify();
}
int Subject::getVal()
{
    return value;
}
void Subject::notify()
{
  // 5. Publisher broadcasts
  for (int i = 0; i < views.size(); i++)
    views[i]->update();
}
Subject::~Subject() {
    // TODO Auto-generated destructor stub
}

} 

更困难和正确的方法是声明抽象接口

IObserverIObservable

这定义了Observer和Observable的通用接口,而我们必须从它们派生类。

观察员.h

#ifndef __IOBSERVER_H__
#define __IOBSERVER_H__
class IObserver
{
public:
    void update() void = 0;
};
#endif  /* __IOBSERVER_H__ */

可观测.h

#ifndef __IOBSERVERVABLE_H__
#define __IOBSERVERVABLE_H__
#include "Observer.h"
class IObservable
{
public:
    void attach(IObserver* pObserver) void = 0;
};
#endif  /* __IOBSERVERVABLE_H__ */

然后导出子

class Subject: public IObservable
{
};
class Observer: public IObserver
{
};

最新更新