MVC

MVCは、アーキテクチャパターンの一種で、役割をM(Model)とV(View)とC(Controller)に分ける方法。

MVCモデルの問題点を解決するPMモデルとMVPモデル - GeekなNooblog

C++で作るので、まずは通知機能を実装する。

observer.hを作成し、

interface_observerのメンバに純粋仮想関数set_subjectとchangedを定義。

subject.hには、

interface_subjectメンバに純粋仮想関数set_observerとnotifyを定義。

これらのメンバ関数が重要な通知機能を担う。

さて、値を受け取るクラスの基底クラスとなるclass_viewだが、

view.hで、interface_subjectとinterface_observerを継承、加えてset_modelを定義。

set_observerでobserverをメンバに持つのと同時に、observer_のset_subjectで自身(this)を指定している。

notifyでメッセージを出力した後、observer_のchangedを呼び出す。

こちらはsubjectをメンバに格納するだけ。

ここのchangedもメッセージ出力だけ。

渡されたmodelのオブザーバーとして自身(this)をセットする。

さて、class_viewからの通知を受け取るclass_controllerは、

こちらはinterface_observerだけ継承。
あとset_viewを持っている。

subjectをメンバにセットするだけ。

メッセージ出力。

渡されたviewのオブザーバーに自身(this)をセット。

さて、class_controllerからメソッドを呼びだすclass_modelだが、

interface_subjectを継承。
実はここにはコントローラから呼び出すメソッドは定義していない。
ここまでのclass_view、class_model、class_controllerには、最低限の通知機能しか用意していない。
それぞれを継承することでMVCを実現できる。
だから、ser_observerとnotifyしかない。

observerをメンバにし、observer_のset_subjectに自身(this)をセット。

メッセージ出力とobserver_のchanged。

さて、class_viewを継承して、class_custom_viewを作成する。

class_custom_modelのオブジェクトポインタと、x_, y_, そして計算結果result_をメンバに持つ。

custom_modelはメンバにセット。
set_modelもしておく。

changedでメッセージを出力した後に、custom_modelからx_, y_, そしてresult_を取得し、メンバにセット。

さて、class_controllerを継承した、class_custom_controllerの実装は、

class_custom_viewとclass_custom_modelのポインタを持ってるので、それらをセットするメンバ関数
そしてchanged。

メッセージ出力、class_custom_viewのメンバの値の出力、そしてclass_custom_modelのfuncを呼び出す。
引数にはcustom_view_のx_, y_を渡す。

custom_viewをメンバにセットし、set_viewもする。

custom_modelをメンバにセットし、custom_view_のset_custom_modelにもセットする。

さて、class_modelを継承した、class_custom_modelの実装は、

x_, y_, result_を取得するメンバ関数と、class_custom_controllerから呼び出される関数func。

funcで引数をx_, y_に格納し、計算結果をresult_に格納、さらにnotifyを呼ぶ。

最後にmain.cppは、

各オブジェクトを生成したら、custom_controller_ptrにcustom_view_ptrとcustom_model_ptrをセットし、custom_view_ptrには値をセット。
custom_view_ptrのnotifyで値が確定するので、これをきっかけに処理が実行され、結果がcustom_view_ptrに反映される。
結果を出力したら、各オブジェクトを解放。

実行すると、

$ vi main.cpp
$ g++ -o main *.cpp
$ ./main
class_view::notify()
class_custom_controller::changed()
custom_view_->x_ = 1
custom_view_->y_ = 2
custom_view_->result_ = 0
class_model::notify()
class_custom_view::changed()
-----
custom_view_ptr->x_ = 1
custom_view_ptr->y_ = 2
custom_view_ptr->result_ = 3
$

Viewの値が確定すると、Controllerに通知が飛び、ControllerはViewの値をModelの関数に渡して値を計算、結果が出たらModelからViewに通知が飛び、ViewはModelから結果を取り寄せ出力。
このように様々な処理を経て、計算結果が出力される。

Sample/designpattern/mvc/mvc/src/mvc at master · bg1bgst333/Sample · GitHub