Observerとは?
あるオブジェクトの状態が変化した際に、
それに関連する他のオブジェクトに自動的に通知する設計。
- 監視者と監視対象を疎結合にできる
- 新しい監視者を簡単に追加できるため、拡張性が高くなる
C++
Observer.cpp
#include <iostream>
#include <vector>
#include <string>
#define STRINGIFY(x) #x
/// <summary>
/// 監視者の抽象クラス
/// </summary>
class Observer
{
public:
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="_subject">監視対象</param>
Observer(class Subject* _subject)
{
subject = _subject;
}
/// <summary>
/// デストラクタ
/// </summary>
virtual ~Observer() = default;
virtual void Update() = 0;
class Subject* subject; // 監視対象
};
/// <summary>
/// 監視対象の抽象クラス
/// </summary>
class Subject
{
public:
/// <summary>
/// コンストラクタ
/// </summary>
Subject()
: observers(new std::vector<class Observer*>())
{
SetState(STRINGIFY(STATE::FINE));
}
/// <summary>
/// デストラクタ
/// </summary>
virtual ~Subject()
{
// コンテナの中の監視者を削除
observers->clear();
// コンテナ自身も削除
delete observers;
}
enum class STATE
{
FINE, // 元気
SOSO, // 普通
BAD, // 悪い
};
/// <summary>
/// 状態を取得する
/// </summary>
inline std::string GetState() { return state; }
/// <summary>
/// 状態の設定
/// </summary>
/// <param name="_state">新しい状態</param>
inline void SetState(std::string _state)
{
state = _state;
StateNotify();
}
/// <summary>
/// 監視者の追加
/// </summary>
/// <param name="_observer">追加する監視者のポインタ</param>
void Attach(class Observer* _observer)
{
observers->push_back(_observer);
}
/// <summary>
/// 監視者の削除
/// </summary>
/// <param name="_observer">削除する監視者のポインタ</param>
void Detach(class Observer* _observer)
{
observers->erase
(
remove
(
observers->begin(),
observers->end(),
_observer
)
);
}
private:
/// <summary>
/// 状態の変化を通知する
/// </summary>
void StateNotify()
{
for (class Observer* observer : *observers)
{
observer->Update();
}
}
std::vector<class Observer*>* observers; // 監視者
std::string state;
};
/// <summary>
/// 状態の監視者
/// </summary>
class StateObserver
: public Observer
{
public:
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="_subject">監視対象</param>
StateObserver(class Subject* _subject)
// 基底のコンストラクタはデフォルトしか呼ばれない
// 自分でどのコンストラクタを呼ぶかを明言する
: Observer(_subject)
{
// 監視者に自身を登録
_subject->Attach(this);
}
/// <summary>
/// デストラクタ
/// </summary>
virtual ~StateObserver()
{
subject->Detach(this);
}
/// <summary>
/// 更新処理
/// </summary>
void Update() override
{
std::cout << "状態の監視者:" << subject->GetState() << std::endl;
}
};
/// <summary>
/// 監視対象「プレイヤー」
/// </summary>
class Player
: public Subject
{
public:
/// <summary>
/// コンストラクタ
/// </summary>
Player() = default;
/// <summary>
/// デストラクタ
/// </summary>
virtual ~Player() = default;
};
int main(void)
{
//監視される対象を作成
Player* player = new Player();
//監視者の作成
std::vector<Observer*> observers = { new StateObserver(player)/* , ・・・ Observerを継承したクラスを無制限で追加できる*/};
std::cout << "状態が少し悪化" << std::endl;
player->SetState(STRINGIFY(Player::STATE::SOSO));
std::cout << "状態が悪化" << std::endl;
player->SetState(STRINGIFY(Player::STATE::BAD));
delete player;
return 0;
}
C#
Observer.cs
using System;
using System.Collections.Generic;
/// <summary>
/// 監視者の抽象クラス
/// </summary>
public abstract class Observer
{
public Subject subject; // 監視対象
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="_subject">監視対象</param>
public Observer(Subject _subject)
{
subject = _subject;
}
public abstract void Update();
}
/// <summary>
/// 監視対象の抽象クラス
/// </summary>
public abstract class Subject
{
private List<Observer> observers = new List<Observer>(); // 監視者
public enum STATE
{
FINE, // 元気
SOSO, // 普通
BAD, // 悪い
};
private STATE state;
/// <summary>
/// 状態を取得する
/// </summary>
public STATE GetState { get { return state; } }
/// <summary>
/// 状態の設定
/// </summary>
/// <param name="_state">新しい状態</param>
public STATE SetState
{
set
{
state = value;
StateNotify();
}
}
/// <summary>
/// 状態の変化を通知する
/// </summary>
private void StateNotify()
{
foreach (Observer observer in observers)
{
observer.Update();
}
}
/// <summary>
/// 監視者の追加
/// </summary>
/// <param name="_observer">追加する監視者のポインタ</param>
public void Attach(Observer _observer)
{
observers.Add(_observer);
}
/// <summary>
/// 監視者の削除
/// </summary>
/// <param name="_observer">削除する監視者のポインタ</param>
public void Detach(Observer _observer)
{
observers.Remove(_observer);
}
}
/// <summary>
/// 状態の監視者
/// </summary>
class StateObserver : Observer
{
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="_subject">監視対象</param>
public StateObserver(Subject _subject)
// 基底のコンストラクタはデフォルトしか呼ばれない
// 自分でどのコンストラクタを呼ぶかを明言する
: base(_subject)
{
// 監視者に自身を登録
_subject.Attach(this);
}
/// <summary>
/// 更新処理
/// </summary>
public override void Update()
{
Console.WriteLine("状態の監視者:" + subject.GetState);
}
}
/// <summary>
/// 監視対象「プレイヤー」
/// </summary>
public class Player : Subject
{
/// <summary>
/// コンストラクタ
/// </summary>
public Player() { SetState = STATE.FINE; }
};
class Program
{
static void Main()
{
//監視される対象を作成
Player player = new Player();
//監視者の作成
List<Observer> observers = new List<Observer> { new StateObserver(player)/* , ・・・ Observerを継承したクラスを無制限で追加できる*/ };
Console.WriteLine("状態が少し悪化");
player.SetState = Player.STATE.SOSO;
Console.WriteLine("状態が悪化");
player.SetState = Player.STATE.BAD;
}
}