CDocument派生クラスがデータおよびそのシリアライズを提供し,データの表示をViewが担当するのがDoc-Viewアーキテクチャである.
このパターン自体には問題がないがMFCが提供するDoc-Viewアーキテクチャにはいささか問題がある.
このパターン自体には問題がないがMFCが提供するDoc-Viewアーキテクチャにはいささか問題がある.
基本となる機能は下記の通りである.
- CView派生クラスはGetDocumentでCDocument派生クラスを取得でき,データにアクセスできる.
- CDocument派生クラスはUpdateAllViewsで表示の更新を全てのCView派生クラスに通知できる.
- ウィザードでDoc-Viewアーキテクチャのサポートのチェックを外す.
- CWinApp派生クラスにCDocumentの代替となる独自のデータクラスを加える.
- CWinApp派生クラスにGetDataなどのデータクラスへのアクセス関数を追加する.
- CWinAppクラスのポインタはグローバル関数GetAfxAppで取得できる.これを実際のCWinApp派生クラスにダウンキャストすればよい.
- データからGUIへの通知にはBoost.Signals2などの汎用的なデリゲータライブラリを用いれば良い.
- その理由はデータクラスはビュークラスに依存すべきでないからである.さもなければ全てのビュークラスのヘッダーファイルをインクルードしその参照を手に入れる必要がある.
リファレンスのExample: Doc-Viewと対してかわりないので公開しておく.
- コンストラクタでModelBase派生クラス(CDocumen派生クラスの代替)をViewBase派生クラス(おそらくCWnd派生クラスと多重継承する)に渡す.
- ModelBase派生クラスはCWinApp派生クラスのメンバーにし,InitInstanceあたりで初期化する.
- 本手法では,新しいビュークラスを追加した場合でも必要なデータを手に入れることができるならば,ModelBase派生クラスを変更する必要がない.
class ModelBase
{
public:
boost::signals2::connection Connect(const signal_t::slot_type &subscriber)
{
return mSignal.connect(subscriber);
}
protected:
boost::signals2::signal<void ()> mSignal;
};
class ViewBase
{
public:
ViewBase(ModelBase& model) : mModel(model) { mConnection = mModel.Connect(boost::bind(&ViewBase::Update, this));}
void Update() { UpdateInternal(); }
protected:
virtual void UpdateInternal() = 0;
private:
boost::signals2::connection mConnection;
ModelBase& mModel;
};

コメントをかく