以前我曾經(jīng)實(shí)現(xiàn)過觀察者模式(signal / slot )。有位朋友不以為然,也把他的實(shí)現(xiàn)發(fā)給我。這是用純OO的方式實(shí)現(xiàn)的,沒有使用模板,不依賴于其它庫。應(yīng)該是仿Java或C#接口。設(shè)計(jì)得不錯(cuò),具有以下特點(diǎn):
1)當(dāng)Subject或Observer 銷毀時(shí),連接自動(dòng)斷開(注冊(cè)自動(dòng)取消),當(dāng)然,這也是實(shí)現(xiàn)該模式的重點(diǎn)。
2)考慮了以下因素:一個(gè)Subject是否允許多個(gè)Observer觀察?一個(gè)Observer是否允許同時(shí)觀察多個(gè)Subject? 由此可分為一對(duì)一,一對(duì)多,多對(duì)多,一般的GUI庫中都是后兩種情況,但自己寫的程序中卻第一種情況居多。所以他出于效率,設(shè)計(jì)了SimpleSubject和SimpleObserver。
不足之處如下:
1)Observer::update()只能帶無類型的參數(shù)(好象也沒有更好的辦法)。
2)由于C++中沒有匿名類,所以使用起來并沒有Java中方便。于是我又添加了一個(gè)ObserverAdapter。
使用舉例:

class A : public Subject
{
int value;
public:
void setValue(int v)
{
value = v;
notify(&value);
}
};

class B : public Observer
{
public:
void update(void* arg)
{
printf("A changed:%d", *(int*)arg);
}
};

void f(A* a, B* b)
{
a->connect(b);
a->setValue(1);
}
使用ObserverAdapter ,則變成了以下情況:
class B
{
ObserverAdapter<B> observerOfA;
public:
B(A* a) : observerOfA(this, &B::valueChanged)
{
a->connect(&observerOfA);
}

void valueChanged(void* arg)
{
printf("A changed:%d", *(int*)arg);
}
};

代碼分為兩個(gè)文件:IObserver.h 和 Observer.h,就貼在下面吧:
IObserver.h : 接口定義

#pragma once

class ISubject;

class IObserver
{
public:
IObserver() {}
virtual ~IObserver() {};

virtual void update(void*) = 0;
protected:
virtual void addSubject(ISubject* ) = 0;
virtual void removeSubject(ISubject* ) = 0;

friend class ISubject;
private:
IObserver(IObserver const&);
IObserver& operator= (IObserver const&);
};

class ISubject
{
public:
ISubject() {}
virtual ~ISubject() {};

virtual void connect(IObserver*) = 0;
virtual void disconnect(IObserver*) = 0;
virtual bool isConnected(IObserver*) const= 0;
virtual void notify(void*) = 0;

protected:
void addObserver(IObserver* observer);
void removeObserver(IObserver* observer);

private:
ISubject(ISubject const&);
ISubject& operator= (ISubject const&);
};


Observer.h : 具體實(shí)現(xiàn)

#pragma once

#include <cassert>
#include <set>

#include "IObserver.h"

//-------------------------------------------------------------------

inline void ISubject::addObserver(IObserver* observer)
{
observer->addSubject(this);
}

inline void ISubject::removeObserver(IObserver* observer)
{
observer->removeSubject(this);
}

//-------------------------------------------------------------------

class SimpleSubject : public ISubject
{
public:
SimpleSubject() : m_observer(0)
{
}
~SimpleSubject()
{
if (m_observer) removeObserver(m_observer);
}
virtual void connect(IObserver* observer)
{
assert(observer);
if (m_observer)
removeObserver(m_observer);
addObserver(observer);
m_observer = observer;
}
virtual void disconnect(IObserver* observer)
{
assert(observer && observer == m_observer);
removeObserver(m_observer);
m_observer = 0;
}

virtual bool isConnected(IObserver* observer) const
{
return observer == m_observer;
}

virtual void notify(void* arg)
{
if (m_observer) m_observer->update(arg);
}
private:
IObserver* m_observer;
};

//-------------------------------------------------------------------

class Subject : public ISubject
{
public:
Subject() : m_observers()
{
}
~Subject()
{
std::set<IObserver*>::iterator
it = m_observers.begin(),
e = m_observers.end();
for (; it != e; ++it)
{
removeObserver(*it);
}
}
virtual void connect(IObserver* observer)
{
assert(observer);
addObserver(observer);
m_observers.insert(observer);
}
virtual void disconnect(IObserver* observer)
{
assert(observer);
removeObserver(observer);
m_observers.erase(observer);
}

virtual bool isConnected(IObserver* observer) const
{
return m_observers.find(observer) != m_observers.end();
}

virtual void notify(void* arg)
{
std::set<IObserver*>::iterator
it = m_observers.begin(),
e = m_observers.end();
while (it != e)
{
(*it++)->update(arg); // observer can be disconnected in update()
}
}
private:
std::set<IObserver*> m_observers;
};

//-------------------------------------------------------------------

class SimpleObserver : public IObserver
{
public:
SimpleObserver() : m_subject(0)
{
}
~SimpleObserver()
{
if (m_subject) m_subject->disconnect(this);
}

ISubject* getSubject() const
{
return m_subject;
}
private:
virtual void addSubject(ISubject* subject)
{
if (m_subject) m_subject->disconnect(this);
m_subject = subject;
}

virtual void removeSubject(ISubject* subject)
{
assert(subject == m_subject);
m_subject = 0;
}

private:
ISubject* m_subject;
};


//-------------------------------------------------------------------

class Observer : public IObserver
{
public:
Observer() : m_subjects()
{
}
~Observer()
{
std::set<ISubject*>::iterator
it = m_subjects.begin(),
e = m_subjects.end();
while (it != e)
{
(*it++)->disconnect(this);
}
}
private:
virtual void addSubject(ISubject* subject)
{
assert(subject);
m_subjects.insert(subject);
}
virtual void removeSubject(ISubject* subject)
{
assert(subject);
m_subjects.erase(subject);
}

private:
std::set<ISubject*> m_subjects;
};

//-------------------------------------------------------------------

template <class T, class Base = SimpleObserver>
class ObserverAdapter : public Base
{
public:
ObserverAdapter(T* t, void (T::*f)(void*))
: m_obj(t), m_func(f)
{
}

virtual void update(void* arg)
{
(m_obj->*m_func)(arg);
}
private:
T* m_obj;
void (T::*m_func)(void*);
};

//-------------------------------------------------------------------
