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

时间:2015-10-31 20:50:39

标签: c++

我尝试使用https://sourcemaking.com/design_patterns/observer/cpp/3

中提供的Observer模式代码

Observer.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 */

Subject.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_ */

Subject.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);
}

它抱怨循环引用。如果我插入课程主题;它说含糊不清的主题。请帮我解决这个问题。

1 个答案:

答案 0 :(得分:0)

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

Subject.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

Subject.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的通用接口,而不是从它们派生我们的类。

Observer.h

#ifndef __IOBSERVER_H__
#define __IOBSERVER_H__

class IObserver
{
public:
    void update() void = 0;
};

#endif  /* __IOBSERVER_H__ */

Observable.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
{
};