インタフェイスには"使う人向け"と"作る人向け"の
二つの側面があるだろうに Java/.NETのinterfaceでは
"使う人向け"のぜんぶあけっぴろげになっちゃうのが気に食わん!
...ので NVI を使った C++版 Obervable/Observer の習作:
/*
* コレがinterfaceに相当する。
* 実装を含むからC#でいうところの
* abstract class だな。
*/
class Observer {
friend class Observable; // Observableにはメソッド公開
private:
// virtualにしない。← NVI
// 単独で呼ばれちゃヤだからprivate.
void notified(Observable* from);
void pre_update(Observable*);
protected:
// 導出側で再定義しる!
virtual void update(Observable* from) =0;
};
#include <algorithm>
#include <list>
#include <string>
using namespace std;
/*
* コレが上記Observerに着火する
*/
class Observable {
private:
typedef list<Observer*> Listeners;
Listeners obs_;
string name_;
public:
explicit Observable(const string& n) : name_(n) {}
void add_observer(Observer* o)
{ obs_.push_back(o); }
void remove_observer(Observer* o) {
Listeners::iterator pos = find(obs_.begin(), obs_.end(), o);
if ( pos != obs_.end() ) obs_.erase(pos);
}
void modified() {
for ( Listeners::iterator iter = obs_.begin();
iter != obs_.end(); ++iter ) {
(*iter)->notified(this);
}
}
string name() const { return name_; }
};
/*
* Observer の実装
*/
#include <iostream>
void Observer::notified(Observable* from) {
pre_update(from);
update(from);
}
void Observer::pre_update(Observable* from) {
cout << from->name() << " 様がお呼びです..." << endl;
}
// ***** こっからおためし *****
#include <iostream>
class Slave : public Observer {
protected:
virtual void update(Observable* from) {
cout << "御用でしょうか " << from->name() << " 様" << endl;
}
};
int main() {
Observable master("ご主人");
Slave slave;
master.add_observer(&slave);
master.modified();
}