1つのプロジェクトのアーキテクチャを設計するとき、彼はMVPパターンに落ち着きました-彼はuiを簡単に変更する能力と、テストでのカバレッジの容易さを買収しました。 ネットワークで見つけたすべてのMVP実装例はC#でした。 Qtで実装すると、いくつかの非自明な瞬間が生じ、その解決策が成功裏に見つかりました。 以下に収集した情報。
MVPストーリー
[1]および[2]からわかるように、MVP設計パターンはMVCの修正であり、オブジェクト指向オペレーティングシステムTaligentで作業するときに、前世紀の90年代にIBMによって最初に使用されました。 後に、MVPはMike Potelによって詳細に説明されました。
MVPとMVCの違いを確認するには、関連する段落[3]をご覧ください
。MVC 、
MVP
QtでMVPを実装する
一般に、[4]に示すように、MVPはすでにQtで暗黙的に使用されています。
しかし、そのようなMVP実装には、いくつかの欠点があります。
- 1人の代表者(プレゼンター)に対して複数のビューを作成することはできません。
- [3]( ここ )で説明されているInversion of Controlパターンを使用することは不可能です。 このスキームでは、ビューは自動的に生成され、インターフェースから継承できません
完全なMVP実装は次のようになります。
したがって、クラス図:
各クラスを検討してください。
- IView-特定のビューが実装するメソッドと信号を定義するインターフェイスクラス([3]の制御の反転を参照)
- Ui :: View -Qtデザイナーの.uiファイルによって生成されたクラス
- ビューは、QWidget(またはその子孫)およびIViewから継承された特定のビューです。 GUIロジック、つまり オブジェクトの動作(たとえば、アニメーション)
- モデル -ドメインデータモデル(ドメインモデル); 変数、フラグ、テーブルモデルなどが含まれます。
- プレゼンター -代表者; モデルとビューの間の相互作用を実装します。 また、それを通して外の世界との相互作用があります。 メインアプリケーション、サーバー(アプリケーションサービスレイヤーなど)など
「正方形を描く」段階では、すべてが明確です。 実装しようとして問題がありました。
- IViewを記述するときは、シグナルを宣言する必要があります。 ただし、このためには、IViewはQObjectから継承する必要があります。 その後、QWidgetとIViewから同時にViewを継承しようとすると、エラーが発生しました。 クラスを2つのQObjectオブジェクトから同時に継承できないことが判明しました(仮想継承でさえも助けにはなりませんでした)。 この問題を回避する方法は[5]: リンクに示されています。 したがって、IViewはQObjectから継承されず、パブリックセクションで完全に仮想(抽象)メソッドとして信号を宣言するだけです。 これは非常に論理的です、なぜなら シグナルは、呼び出しによってオブザーバーにスロットを通じて通知される関数でもあります(Observerパターンを参照)。
- PresenterクラスでIViewシグナルをバインドするときに別の問題が発生しました。 実際には、PresenterにはIViewへのリンクが含まれています(実行時に特定のビューがPresenterに追加されますが、IViewとして保存されます-ポリモーフィズムが使用されます)。 ただし、信号とスロットを接続するには、静的
QObject::connect()
メソッドを使用します。これは、オブジェクトとしてQObjectの子孫のみを受け入れ、IViewは受け入れません。 しかし、我々の見解のいずれかがそれであることを知っています。 [6]に示すように、問題は動的型変換によって解決されます。
QObject * view_obj = dynamic_cast < QObject *>( m_view ); // m_view - IView
QObject :: connect ( view_obj , SIGNAL ( okActionTriggered ()),
this , SLOT ( processOkAction ()));
また、IViewを実装するときは、ヘッダー(.h)ファイルのみが必要であることに注意してください。 IView用に.cppファイルを作成した場合は、削除する必要があります。削除しないと、コンパイルの問題が発生する可能性があります。
原則として、この情報はQtにMVPを独立して実装するのに十分ですが、簡単な例を示します(実際のアプリケーションのコンテキストでの相互作用を考慮せずに、MVP実装のみ)。
QtでMVPを使用する簡単な例
アーカイブには3つの例があります。これは同じアプリケーションですが、各例に追加があります。
- MVPの実装
- 複数のビューを作成する機能を追加しました
- データ変更時のビュー間の完全な同期
すべてのコードは、Doxygenスタイルでコメントされています。 Doxywizardを使用して簡単にドキュメントを生成できます。
ここからサンプルをダウンロード
範囲外
記事に含まれていないトピックに関する興味深い質問のリストを次に示します。
- 結果のシステムのモジュールをテストする
- MVPのコンテキストでのライブラリとしてのViewの実装(QtPluginを使用)
- MVPのコンテキストでQtDeclarative(QML)を使用したViewの実装
- クラスファクトリを介してPresenterにビューを渡す(したがって、スタイルを簡単に変更できる)
これらの問題に関する情報は、コメントで歓迎されています。
ソース
- http://www.rsdn.ru/article/patterns/generic-mvc2.xml
- http://en.wikipedia.org/wiki/Model-view-presenter
- http://www.rsdn.ru/article/patterns/ModelViewPresenter.xml
- http://thesmithfam.org/blog/2009/09/27/model-view-presenter-and-qt/
- http://doc.trolltech.com/qq/qq15-academic.html
- http://developer.qt.nokia.com/forums/viewthread/284