増補改訂版Java言語で学ぶデザインパターン入門 結城 浩 第17章 Observer をC++で実装

自分のお勉強用 : デザパタ 結城本 第17章 Observer をC++で適当に実装

C++とデザパタのリハビリを目的として。
なんかObserverってスレッド化しないと、なんかしっくりこないというか。
イマドキだと関数化なのかな。

写経元は書籍「増補改訂版Java言語で学ぶデザインパターン入門 結城 浩」の第17章 Observer。

ファイル一覧

  1. myObserver.h : インターフェイス
  2. myObserverA.cpp と .h
  3. myObserverB.cpp と .h
  4. NumberGenerator.cpp と .h
  5. RandomNumGenerator.cpp と .h
  6. observer_cpp.cpp(main部分)
インターフェイスを「myObserver」という名称にしています。
普通に「Observer」を使うと、なんだか最近だと標準ライブラリかどこかに存在しているようで紛らわしかったので。
IObserverとしても良かったです。

実装


記載順序は以下とします。
インターフェイス → IF実装 → Subject → Subject実装 → main。

myObserver.h : インターフェイス

#pragma once
#include "NumberGenerator.h"
class myObserver
{
  friend class NumberGenerator;
public :
  myObserver() :next_(nullptr) {};
  virtual ~myObserver() {}
  virtual void update(NumberGenerator&) = 0;
private:
  myObserver* next_;
};

myObserverA.h : IF実装その1

#pragma once
#include "myObserver.h"
#include "NumberGenerator.h"
class myObserverA : public myObserver
{
 friend class NumberGenerator;
public:
 void update(NumberGenerator&);
};

myObserverA.cpp : IF実装その1

#include "myObserverA.h"
#include 
#include  //sleep—p
using namespace std;
void myObserverA::update(NumberGenerator& numGen)
{
 cout << "AAA:" << numGen.getNumber() << endl;
 Sleep(100);
}

myObserverB.h : IF実装その2

#pragma once
#include "myObserver.h"
#include "NumberGenerator.h"
class myObserverB :
 public myObserver
{
 friend class NumberGenerator;
public:
 void update(NumberGenerator&);
};

myObserverB.cpp : IF実装その2

#include "myObserverB.h"
#include 
#include  //sleep—p

using namespace std;

void myObserverB::update(NumberGenerator& numGen)
{
 cout << "BBBBBBBB:" << numGen.getNumber() << endl;
 Sleep(100);
}

NumberGenerator.h : Subject

#pragma once
#include "myObserver.h"
//これはデザパタで言うSubjectクラス。
class NumberGenerator
{
 friend class myObserver;
public :
 NumberGenerator();
 ~NumberGenerator() {};
 void addObserver(myObserver* observer);
 void removeObserver(myObserver* observer);
 void notifyObservers();
 virtual int getNumber() = 0;
 virtual void execute() = 0;
private :
 myObserver* obs_[3]; //3固定で実験。
 int numObs_;
 myObserver* current_;
};

NumberGenerator.cpp : Subject

#include "NumberGenerator.h"
NumberGenerator::NumberGenerator() :current_(nullptr), numObs_(0)
{
 obs_[0] = nullptr;
 obs_[1] = nullptr;
 obs_[2] = nullptr;
}

void NumberGenerator::addObserver(myObserver* observer)
{
 observer->next_ = current_;
 current_ = observer;
}

void NumberGenerator::removeObserver(myObserver* observer)
{
 //リスト型ポインタ操作をする。めんどいので省略。
}

void NumberGenerator::notifyObservers()
{
 myObserver* o = current_;
 while (o != nullptr) {
  o->update(*this);
  o = o->next_;
 }
}

RandomNumGenerator.h : Subject実装

#pragma once
#include "NumberGenerator.h"
//Randomじゃなくていいや。めんどい。
class RandomNumGenerator :
 public NumberGenerator
{
public:
 RandomNumGenerator():current(0) { } //0で初期化。
 ~RandomNumGenerator() {}
 int getNumber() { return current; }
 void execute();
private:
 int current;
 int getRandomSimulate() { return current + 1; } //ランダムめんどいので+1するお遊び。
};

RandomNumGenerator.cpp : Subject実装

#include "RandomNumGenerator.h"
void RandomNumGenerator::execute()
{
 for (int i = 0; i < 10; i++) {
  current = getRandomSimulate(); //実質1~10とかかな。
  notifyObservers();
 }
}

observer_cpp.cpp : メイン

#pragma once
#include "myObserverA.h"
#include "myObserverB.h"
#include "RandomNumGenerator.h"

int main()
{
 RandomNumGenerator generator;
 myObserverA obA;
 myObserverB obB;
 generator.addObserver(&obA);
 generator.addObserver(&obB);
 generator.execute();
}

所感

C++は一番好きなのですが、イマドキの言語に慣れると気合を入れないと書けないのがネックですね。

最近は「NULL」を「nullptr」とか記載するんですねぇ。

一つ前の記事で「HeadFirstデザインパターン」を参考にしたんですが、そちらの初っ端もObserverだったのに気付きまして。
次の投稿でそれはフォローしようかな。

コメント

このブログの人気の投稿

windows10 で nvidia のグラボのcode43現象を解決した

Java : processbuilder 標準出力 タイムアウト

GTX560Ti がおかしい(code 43が出る)(2018年)→解決しました(2019)