PureMVCフレームワークの勉強メモ

以前は自分のプロジェクトの UI 層にシンプルな UI フレームワークを使用していましたが、スケーラビリティが弱く、大規模なプロジェクトでの複数人でのコラボレーションにも問題があったため、より古典的な MVC ベースの PureMVC とMVVM ベースの Loxodon Framework. 今日は PureMVC. 研究に関する情報を記録します。

MVCの考え

MVCとは何ですか?

MVCの正式名称は Model View Controller といい、model-view-controller の略であり、ソフトウェア設計モデルです。ビジネス ロジック、データ、インターフェイス表示を分離する方法を使用してコードを整理し、多数のビジネス ロジックを 1 つのコンポーネントにまとめます。インターフェイスとユーザー インタラクションは改善してパーソナライズする必要がありますが、ビジネス ロジックを書き直す必要はありません。エンコード時間を短縮します。

MVC はデスクトップ プログラムに存在し始めました。M はビジネス モデル、V はユーザー インターフェイス、C はコントローラーを指します。

MVC を使用する目的は、M と V の実装コードを分離し、同じプログラムで異なる表現形式を使用できるようにすることです。モデル層とビュー層はコントローラーを通じて分離され、同様に、MVVM と MVP も VM と P を通じてモデル層とビュー層を分離します。このアイデアを採用する利点は、M と V の間の結合が軽減され、拡張、再利用、管理が容易になることです。

クリップイメージ006

図:MVC構造図(実線→依存関係を表す、破線→イベント、通知などを表す)

MVC の中心的な考え方は、コードの再利用性と関心の分離です。

モデル: データ モデルは、アプリケーションのビジネス ロジックとデータの処理方法に関連するデータをカプセル化するために使用されます。モデルはデータベースへのアクセスなど、データに直接アクセスできます。「モデル」は「ビュー」と「コントローラ」に依存しません。モデル内のデータは通常、更新メカニズムを通じて解放されます。このメカニズムを実装するには、このモデルを監視する必要があるビューを最初にこのモデルに登録する必要があります。モデル: データ モデルの監視変更を実現します。(オブザーバーパターン「パブリッシュとサブスクライブ」)

ビュー(View): ビューレイヤーは目的に応じたデータの表示を実現します(オプション機能)。通常、View にはプログラム ロジックはありません (単純な表示インターフェイスを使用できます)。ビューに更新機能を実装するには、ビューが監視するデータ モデル (モデル) にアクセスする必要があるため、最初にビューが監視するデータを登録する必要があります。

コントローラー: コントローラーはさまざまなレベルで組織的な役割を果たし、アプリケーションのフローを制御するために使用されます。イベントを処理し、応答します。「イベント」には、ユーザーの行動やデータ モデルの変更が含まれます。

シンプルなUIフレームワーク

1. UIフレームワークのコアメソッド

  • BaseUI は UI の名前を記録し、コントローラーは UI を特定の操作メソッドから分離するために使用されます。
  • UIManager は辞書を使用してすべての UI コンポーネントを記録し、UI を開いたり閉じたりするためのいくつかのメソッドを提供します。
  • EventManager(メッセージシステム)は、異なるモジュール間の連携を実現するもので、通常、メッセージシステムはオブザーバーモードを利用して複数のメソッドをキーワードで登録(サブスクライブ)し、そのキーワードを用いて登録されたメソッドに通知を行います。

2. UIフレームワークの拡張方法

  • ResourceManager (リソース マネージャー) は、同期読み込み、非同期読み込み、読み込みとインスタンス化など、Resources リソースを読み込むいくつかのメソッドをカプセル化します。
  • DataHelper (データ パーサー) は、XML、Json、Protobuf、およびその他のデータ形式のシリアル化および逆シリアル化プラグインをさらにカプセル化します。
  • シングルトン シングルトン パターン
  • Common Extension (パブリック拡張コンポーネント) は、ジェネリックスと拡張メソッドを使用して Unity でメソッドをさらにカプセル化し、開発を高速化します。

3. シンプルなUIフレームワークのメリットとデメリット

  • 使いやすい
  • C# 初心者にとっては比較的理解しやすい
  • 非常に小規模なプロジェクトにのみ適しています
  • スケーラビリティが非常に悪い
  • MonoBehaviour スクリプトの下にロジックが積み重なることになり、効率が低下します。

上記の単純な UI フレームワークの落とし穴を経験した後、より大規模なプロジェクト、または複数の人々による協力的でオープンなプロジェクトには、基盤としてより信頼性の高いフレームワークが必要であることに気付きました。Unity にはいくつかの一般的なフレームワークがあります。これも古典的なフレームワークの拡張です。PureMVC、LoxodonFrameworkなど。

PureMVC フレームワーク

PureMVC の長所と短所:

  1. 仲介者、エージェント、コマンド パターンを使用して分離を実現し、モデル、ビュー、コントローラーの直接結合を使用して分離をより徹底的に削減し、一部のコードの再利用性を向上させます。
  2. View インターフェイスと Model データの両方を再利用できます
  3. コードが冗長すぎるため、単純な機能の場合は、対応する View、Mediator、Command、Facade、Proxy、Model などのスクリプトを作成する必要があります。
  4. 操作手順が比較的面倒で、Mediatorのコードも複雑でわかりにくい印象です。
  5. メッセージはリフレクションの形式でパフォーマンスをより重視します (新しいバージョンではすでに委任が使用されています)。

PureMVC の機能:

  1. 通知の配信にはボックス化およびボックス化解除操作が必要です (新しいバージョンでは汎用委任が採用されています)。
  2. コマンド/通知はオブザーバー モードで実装され、リフレクションを使用してメソッドを取得して実行します (新しいバージョンはデリゲートするように変更されています)。
  3. 自分で追加する必要があるサービスモジュールはありません
  4. そしてデータは通知を介して渡されます SendNotification にはオブジェクト型パラメータが 1 つだけありますが、データ送信が第一であるように感じられます データをクラスに結合して渡すことができ、クラスを制約するだけで済みます

PureMVC コア スクリプト //コア ファイル

1.View.cs : IView.cs

  1. ディクショナリ mediatorMap は、登録されたメディエーターを記録します (キーはメディエーター名、値はメディエーター インターフェイス)
  2. ObserverMap ディクショナリには、登録されたオブザーバーが記録されます (キーはイベント名、値はオブザーバー インターフェイス)
  3. メディエーターとオブザーバーを登録/登録解除するメソッドを提供します (登録、削除)
  4. コア メソッドはオブザーバー メソッド NotifyObervers に通知します。
  5. ビューシングルトンの実装


IView.cs インターフェイスは、View 2.Controller.cs: IController.csによって実装されるメソッドを指定します。

  1. 辞書 commandMap は、登録されたコマンドを記録します (キーはコマンドの名前、値は Func<ICommand>)
  2. ビューで通知を実行するための IView インターフェイスを記録します。IView には、コントローラーの構築時に値が割り当てられます。
  3. コントローラーシングルトンの実装
  4. 登録、キャンセル、コマンド実行(登録、削除、実行)のためのインターフェースを提供します。
  5. IController.cs インターフェイスは、View によって実装されるメソッドを指定します。

3.Model.cs :IModel.cs

  1. 辞書 proxyMap は、登録されたモデル プロキシ (Proxy) を記録します (キーはプロキシ名、値はプロキシ タイプ インターフェイス)
  2. IModel を実装するためのメソッド (登録、キャンセル、プロキシ取得メソッドなど)
  3. モデルシングルトンの実装
  4. IModel.cs インターフェイスは、Model によって実装されるメソッドを指定します。

GameObject: 基本的に最下層 (UI ビュー) であり、Unity 独自のコンポーネントを除く PureMVC クラスには依存しません。

Mediator: GameObject のみに依存し、GameObject と 1 対 1 でバインドされます。GameObject の入力は、eventsを通じてMediator 呼び出しに渡されます。

コマンド: 最下層はメッセージ システムを介してメディエーターと通信し、プロキシに依存します (一部の操作を実行するにはプロキシを介してエンティティを取得する必要がある場合があり、プロキシは一部のデータ操作のみを実行するため)。

プロキシ: 最下層。対応するデータ クラス以外のどのクラスにも依存しません。

ビュー: シングルトン。オブザーバー モードにメッセージ システムを組み込むことに加えて、その責任はメディエーター (登録、削除、取得、所有) の管理のみです。

コントローラー: シングルトン、メッセージ システムのリッスン メソッドを内部で呼び出します。その責任はコマンド (登録、削除、実行、ハス) の管理のみです。

モデル: シングルトン、プロキシ (登録、削除、取得、ハッシュ) の管理のみを担当します。

Facade: Singleton、View、Controller、Modelの管理を担当 Viewはメッセージシステムを持っているため、間接的にメッセージを送信する機能も持ちます。

Notifier: Facade のメッセージ システムを呼び出して他のオブジェクトに通知する機能クラス。したがって、基本的に View のメッセージ システム (Observer) を呼び出してメッセージを送信します。

これらのクラスの機能から、各クラスが単一の責任を持ち、機能が明確に分離されていることがわかります。コントローラーは、対応する Type を使用してメソッドを呼び出すオブジェクトを作成し、コマンドが実行されるたびにクラスをインスタンス化します。Observer メッセージ システムは、リフレクション オブジェクトのメソッド名 (GetMethod) を使用して観測オブジェクトのメソッドを呼び出しますが、新バージョンではこの問題を解決するために汎用委任を使用しました。

図: PureMVC 設計図 (公式 Web サイト                                から引用)

設計図からは、コア レイヤーの Facade に加えて、Mediator、Proxy、および Command があることが明確にわかります。

PureMVC フレームワークの目標は非常に明確で、プログラムをモデル、ビュー、コントローラーの 3 つの結合度の低い層に分割します。Facadeで一元管理されています。

  1. モデルは、プロキシ オブジェクトへの参照を保存します。プロキシは、データ モデルを操作し、リモート サービスと通信してデータにアクセスする責任を負います。
  2. View は Mediator オブジェクトへの参照を保持します。特定のビューコンポーネント「ViewComponent」は Mediator オブジェクトによって操作されます
  3. コントローラーはすべてのコマンドのマッピングを保存します。Command は Proxy オブジェクトを取得してそれと対話し、Notifacation を送信して他のコマンドを実行できます。(本質はやはり View 内の観測システムです)
  4. プロキシはデータ モデルの操作を担当します。データ モデルとは何ですか? データモデルはデータベースやXMLなどです。Proxy は、データ モデルに対するクエリ、挿入、更新、削除などの操作に使用されるクラスであることが直感的に理解できます。操作が完了すると、他のレイヤーに更新するように通知する通知メッセージが送信されます。プロキシは情報を送信するだけであり、カップリングを避けるために情報を監視しません。
  5. Mediator は、イベント リスナーの追加、通知の送信または受信、ビュー コンポーネントのステータスの直接変更など、特定のビュー コンポーネントの操作を担当します。たとえば、ボタンにイベントを追加し、ボタンがクリックされたときに通知を送信し、対応する操作を実行するようにコントローラーに指示します。たとえば、ログイン ボタンの場合、メディエータはコントローラに通知を送信し、ログイン操作を実行するように指示します。Mediator は、ビューの状態を直接変更する責任もあります。たとえば、ログイン ボタンをクリックした後、Mediator は操作の繰り返しを避けるためにログイン ボタンをグレーに変更します。ログイン操作中などを知らせるメッセージをビューに表示することもできます。概要 Medoator は特定のビューを管理するために使用されます。
  6. コマンドは、プロキシ オブジェクトを取得して対話し、通知を送信することで他のコマンドを実行できます。たとえば、ログイン ボタンをクリックした後、メディエーターはコントローラーに対応するコマンドを実行するように指示します。ログインにはユーザーの情報を知っている必要があるため、コマンドはプロキシにデータベースまたは他のデータ モデルをクエリして、対応するデータにアクセスするように指示します。プロキシがデータをクエリした後、クエリが完了したことをコマンドに通知する通知を送信し、検証のためにその情報をコマンドに返します。同時に、メディエータもプロキシから送信された通知を受信し、情報がビューを通じて検証されていることをユーザーに伝えます。コマンドはユーザー情報を検証した後、検証結果を仲介者に返す通知を送信し、検証結果をユーザーに通知します。または、コマンドは、ユーザー情報の詳細の読み取りの確認など、他のコマンド操作を実行するために通知を送信することもできます。

PureMVC 設計パターン

プロキシ パターン: このオブジェクトへのアクセスを制御するために、他のオブジェクトにプロキシを提供します。

使用法: PureMVC のプロキシ モードは、データと他のシステム間の直接の対話を分離し、データのプロキシ クラスを通じて動作します。プロキシ クラスは Notifier から継承しているため、プロキシは Notifier.facade とコントローラーを通じてビューにもアクセスできます。これにより、データ クラスと他のクラスの間の結合が効果的に分離され、データ クラスの再利用性が向上します。このようなデータ クラスのデータは計画ツールで生成できるため、開発がより便利になります。

外観モード: サブシステムのインターフェイスのセットに一貫したインターフェイスを提供します。このモードは、サブシステムを使いやすくするための高レベルのインターフェイスを定義し、依存関係の逆転とデメテルの法則を完全に具体化します。出現パターンを使用すると、サブシステム間の依存関係を減らすことができます。古いサブシステムの Facade クラスをセットアップし、その Facade クラスを使用して新しいシステムと対話することで、古いシステムの情報システムへの依存を減らし、複雑な関係を作成できます。

使用法: PureMVC のアピアランス モードを使用して記述された Facade クラスは、MVC フレームワーク全体の主要な外部インターフェイスです. View、Model、Controller は Facade クラスに記録され、シングルトンが実装されています. MVC コア クラスにほぼすべての外部インターフェイスがあります典型的な高レベル インターフェイスです。

オブザーバー パターン: 複数のオブザーバー オブジェクトがテーマ オブジェクトを同時に監視できるようにする 1 対多の依存関係です。テーマ オブジェクトが変更されると、すべてのオブザーバー オブジェクトが通知され、オブジェクト自体が自動的に更新されます。

使用法: PureMVC フレームワークでは、オブザーバー モードを使用し、メディエーター クラスのコンストラクターでメディエーターに対応する UI イベントを登録します。UI がイベントをトリガーすると、メディエーターはビューを通じてオブザーバーに通知を送信します。ビュー 各イベントに対応するオブザーバーの辞書を記録し、オブザーバーを走査して、通知内の特定のイベントを実行します。通知イベントは、メディエーターの構築時に ListNotificationInterests メソッドをオーバーライドすることによって追加されます。PureMVC のコマンド モード実装は通知も送信し、オブザーバーがコントローラーで ExcuteCommand を呼び出すことによってトリガーされたコマンドを実行できるようにします。

 メディエーター パターン: メディエーター オブジェクトを使用して、一連のオブジェクトの対話をカプセル化します。メディエーターはオブジェクト間の明示的な参照の必要性を排除し、オブジェクトを疎結合にし、オブジェクト間の相互作用を独立して変更できるようにします。

メディエーターの長所と短所は明らかです。具体的なクラス間の結合が軽減され、各型を独立して変更および再利用できるようになります。欠点は、ロジックの複雑化に伴い仲介者の制御がより複雑になり、仲介者の負担が大きくなりすぎることです。

使用法: PureMVC フレームワークで中間パターンを使用して、ビュー層とコントローラー層およびモデル層の間の結合を効果的に分離します。ビューは、保持するデータ プロキシを通じて操作とデータ処理を効果的に実行できます。

コマンド モード: リクエストをオブジェクト (つまり、作成したコマンド オブジェクト) としてカプセル化し、顧客がさまざまなリクエストでパラメータ化できるようにします。リクエストをキューに入れたり、リクエスト ログを記録したり、取り消し可能な操作をサポートしたりできます。

抽象コマンド コマンド: コマンドのインターフェースを定義し、実行方法を宣言します。

具体的なコマンド ConcreteCommand: 特定のコマンドは実行されるメソッドを実装します。通常は仮想実装であり、通常はコマンドを実際に実行するオブジェクトであるレシーバー (Receiver) を持ちます。コマンドに必要な対応する機能を実装できる限り、どのクラスでも受信者になることができます。

呼び出し側: コマンド オブジェクトにリクエストの実行を依頼します。通常はコマンド オブジェクトを保持しており、多くのコマンド オブジェクトを保持することができます。ここは、クライアントが実際にコマンドをトリガーし、対応する操作を実行するようコマンドに要求する場所であり、コマンド オブジェクトへの入り口に相当します。

クライアント クライアント: コマンドはクライアントによって作成され、コマンドの受信者が設定されます。

使用法: SimpleCommand と marcoCommand は ICommand インターフェイスを継承し、Execute メソッドを実装します。コード内で SendNotifacation を呼び出すと、通知が View.NotifyObserver() メソッドでオブザーバーに通知されます。オブザーバーはコントローラーで ExecuteCommand を実行します。ExecuteCommand は辞書からコマンド インターフェイスを取得し、Execute を呼び出してコマンドを実行します。コマンドを書き換えて解決を実現します。

シングルトン パターン: シングルトン パターンは最も一般的に使用されるデザイン パターンで、その名前が示すように、クラスにはインスタンスが 1 つだけあります。

シングルトン パターンはグローバル アクセス ポイントを提供し、プログラム開発をより柔軟にしますが、シングルトン クラスの増加によりコードの過度の結合が発生し、再利用とメンテナンスが減少します。

使用法: PureMVC では、Facade、View、Model、Controller はすべてシングルトン モードを実装し、バッチ アクセスをより便利にし、volatile キーワードを追加します (volatile は主にマルチスレッド環境で使用されます。変数が volatile として定義されている場合、読み取り時にこの変数の値は、キャッシュから読み取るのではなく、毎回メモリから読み取られます。これは、他のスレッドがこの変数を更新する方法に関係なく、変数から読み取られた情報が最新であることを保証するために行われます)。呼び出し側のインターフェイス。
 

ファサード デザイン パターン: 開発プロセス中に、コントローラーでビューとモデル オブジェクトを取得し、モデルを変更し、ビューを更新するか、ビューでモデルを取得し、初期化操作を実行する必要があります。ロジック、モデル、ビューとコントローラー間の呼び出しが頻繁に行われ、結合が強化されます PureMVC では、上位層のインターフェイスがすべてのコア層 (モデル、ビュー、コントローラー) の管理と操作を担当しますPureMVC では、Facade デザイン パターンを開発しました。

外観デザイン パターンの定義: 「サブシステムまたはインターフェイスのグループに統一インターフェイスを提供して、複雑さを簡素化し、結合を軽減します。」

Facade クラスは抽象クラスとして扱われ、直接インスタンス化されることはありません。特定のアプリケーションを実装するには、具体的に Facade のサブクラスを作成し、Facade メソッドを追加またはオーバーライドする必要があります。このクラスの名前は「ApplicationFacade」です(もちろん好きな名前を付けてください)。

前述したように、これは主にモデル、ビュー、コントローラーへのアクセスと通知を担当します。それはこの3つを管理することです。

ファサードは、モデル、ビュー、コントローラーの「ブローカー」です。実際にコードを書く際には、これら 3 つのクラス ファイルをインポートする必要はなく、直接使用する必要もありません。Facade クラスには、構築メソッドに 3 つのコア MVC シングルトンの構築がすでに含まれています。

Facade クラスは、コンストラクターで Model、View、Controller オブジェクトを初期化し、それらへの参照をメンバー変数に保存します。

このようにして、Facade はモデル、ビュー、コントローラーにアクセスできます。このようにして、コア層のすべての操作がファサードに集中され、開発者がコア層を直接操作することができなくなります。

ファサードの初期化

一般に、実際のアプリケーションにはファサード サブクラスがあり、このファサード クラス オブジェクトは、プロキシ、メディエータ、およびコマンドの初期化、コマンド名と通知名の間のマッピングの確立、またはコマンドの実行によるすべてのプロキシとメディエータの登録を担当します。

このとき、コマンド、プロキシ、メディエーターについて言及しましたが、実際には次のような対応関係になります。

プロキシ=>モデル

メディエーター=>表示

コマンド=>コントローラ

モデルとプロキシとは何ですか?

上のスクリーンショットから、モデルとプロキシの関係図がわかります。

モデルはデータ(Data Object)であり、ゲームはデータによって動かされます、例えば、HP、MP、金貨、レベル、スキルなどのキャラクターデータは、PureMVC の Proxy を通じて管理されます。プロキシは、「そのオブジェクトへのアクセスを制御するために他のオブジェクトにプロキシを提供する」プロキシ設計パターンであり、PureMVC でデータ モデルを制御および管理するために使用されます。

「データオブジェクト」とは、データを任意の構造で格納するオブジェクトです。つまり、モデルと直接通信することはなく、モデルへのすべての追加、削除、変更、クエリはプロキシを通じて処理されます。

代理店モデルに関しては、例えば、スター選手クリスティアーノ・ロナウドの代理人はクリスティアーノ・ロナウドチームであり、すべてのビジネス協力事項はクリスティアーノ・ロナウドチームを通じて処理されるため、クリスティアーノ・ロナウドは協力コストを支払う必要がありません。すべてのことをクリスティアーノ・ロナウドを介さずに(内部実装の詳細をある程度隠す)、チームはクリスティアーノ・ロナウドが多くの問題を処理できるように支援することもできます。コードの観点からも、「1 つを変更しても他のデータには影響しない」という満足感も得られます。一部のデータに対する変更は、他のデータに影響を与えるべきではありません。
引き続き上の図を見て、モデルの矢印に注目してみましょう。モデルはファサードとのみ相互作用します。上で述べたように、これは結合を減らすためです。

その隣の Objs は Model であり、これは Proxy に相当しますが、1 つの Model が 1 つの Proxy に対応しているわけではありません。そうすると、非常に面倒になります。たとえば、モジュールにはさまざまな Model データが含まれる場合があり、複数の異なる Model データを定義できます。モデルですが、プロキシを介して管理できるため、より便利です。 

モデル データは通常、同期的に取得または設定されます。プロキシは、DataObject の一部のプロパティまたはメソッドにアクセスするための API を提供することも、DataObject への参照を直接提供することもできます (ただし、これはお勧めできません。モデルを保護し、アクセス用の対応するインターフェイスを提供する必要があります)。DataObject を更新するメソッドが提供されている場合、データが変更されたときに通知が送信され、システムの他の部分に通知されます。

ここでの通知通知は、実際にはオブザーバー モードです。オブジェクトが変更されると、他の多くのオブジェクトもそれに応答する必要があります。このとき、オブザーバー モードが使用され、特定の WeChat パブリックにサブスクライブするなどのパブリッシュ/サブスクライブ モードが使用されます。アカウントを作成すると、パブリック アカウントが記事を公開し、購読しているすべてのユーザーがリマインダーを受け取ることができます。これはゲーム内のあらゆる場所で行われます。モデルが変更されると、View コンポーネントが更新するように通知されます。次に、View には、通知通知を処理し、対応する論理処理を実行するための対応するメソッドが存在します。

プロキシは、通知通知 (データ変更時) のみを送信し、通知通知を処理せず、View コンポーネントがどのように変更されるかは考慮しません。

Proxy オブジェクトは、Mediator オブジェクトを参照または操作することによって、DataObject (データ オブジェクト) が変更されたことをシステムに通知してはなりません。

つまり、Mediator は Proxy を取得できますが、Proxy で Mediator を取得する必要はありません。View レイヤーに更新を通知したい場合は、Notification 通知を送信するだけです。

(プロキシは、これらの通知が発行された後にシステムにどのような影響を与えるかを考慮しません)

このように、プロキシとメディエータの間には一方向の結合のみが存在します。

Proxyには特定のロジック処理部分も含まれており、Model層とそれに付随するView層やController層を可能な限り分離するために、Domain Logic(ドメインロジック)をProxy内に実装しています。

たとえば、メディエーターまたはコマンドで税控除を計算する関数を実装する場合、コードのこの部分を結合することと同じです。たとえば、ビューを再構築する必要があるか、他のコマンドでも税控除関数を使用する必要があります。の場合、コードのこの部分は再利用できないため、プロキシに配置する方が適切です。

データ型変換について

モデル (データ オブジェクト) は通常、複雑なデータ構造であるため、多くの場合、そのプロパティの一部を参照し、型を必要なデータに変換する必要があります。

getter プロパティと setter プロパティを通じて、この頻繁に発生する型変換の問題をうまく解決するのに役立ちます。

データ オブジェクトの特定の部分を取得するには、複数の異なるタイプのゲッターを定義する必要がある場合があります。

public ArrayCollection searchResultAC 

 get {データを ArrayCollection として返す;}

 }

これは公式ドキュメントの例ですが、モバイル側では、毎回変換することによるメモリの消費と GC の発生を避けるために、やはりキャッシュすることをお勧めします。

ビューとメディエーターとは何ですか?

ビューはビューコンポーネントであり、モデル層と同様に「メディエーター」によって管理され、メディエーターによって操作される特定のビューコンポーネント(ビューコンポーネント)です。これには、イベント リスナーの追加、通知の送受信、ビュー コンポーネントの状態の直接変更が含まれます。

メディエーター (メディエーター設計パターン):

「中間オブジェクトを使用して、一連のオブジェクトの対話をカプセル化する」 (重い対話、強力なロジック)

※ビューコンポーネントとは、UI上の各種コントロール、ボタン、リスト、スクロールバーなどを指します。

これを行うと、ビューをそれを制御するロジックから分離します。View でのコンポーネントの定義と初期化は Mediator で定義および実装されるため、UI を再構築しても Mediator のみが変更されます。

Mediator は Proxy とやり取りすることが多いため、Mediator のコンストラクターで Proxy インスタンスへの参照を取得し、それを Mediator のプロパティに保存することが必要になることがよくあります。これにより、Proxy インスタンスを頻繁に取得することによって生じるパフォーマンスのオーバーヘッドを回避できます。

ここでわかるように、通常、ビューとメディエーターの間には 1 対 1 の関係がありますが、一部のビューは比較的複雑で、複数のサブ UI で構成されています。メディエーターは複数のビュー コンポーネント参照 (メディエーターの異なるサブ UI) を持つこともできます。同じ機能です)。

ただし、Mediator が大きすぎる場合は分割する必要があるため、すべてをまとめて処理するよりも、分割されたサブモジュールの Mediator で処理する方が適切です。作業のこの部分はゆっくりと再構築する必要があります。

ビューコンポーネントタイプの変換

(この部分はModelと同じ扱いになります)

この Mediator サブクラスは、その View Component パラメーターをコンストラクター内の親クラスに渡し、内部で保護属性 (viewComponent) に割り当てられ、Object 型に転送されます。

Mediator が構築された後、setViewComponent 関数を呼び出すことで、その View コンポーネントを動的に割り当てる (変更する) ことができます。その後、このオブジェクトの API にアクセスする必要があるたびに、オブジェクトを実際の型に手動で変換する必要があります。これは退屈で繰り返しの作業です。

上記のモデルと同様に、ビューへの参照は Mediator に保存され、それをキャッシュします。

メディエーターが通常行うこと:

1. ビューコンポーネントのプロパティを確認または変更します

2. Proxy オブジェクトによって公開されたプロパティを確認または変更します

3. 1 つ以上の通知を送信して、他のメディエーターまたはコマンドに応答するように通知します (それ自体に送信される場合もあります)。

ただし、注意すべき点は、ビジネス ロジック (ビジネス ロジック) はメディエーターではなくコマンドに配置する必要があるということです。

実際、Mediator は複雑なロジックを処理しません。モデルと同様に、ドメイン ロジック部分も Mediator に実装できます。これにより、Controller との結合が軽減され、再利用性が向上します。

注: VC (ビュー コンポーネントおよびプロキシ) プロパティの検出または変更をビジネス ロジック (ビジネス ロジック) としてみなさないでください。

以下に役立つ教訓をいくつか示します。

1. 複数の調停者が同じイベントに応答する場合、通知が送信され、関連する調停者がそれに応じて応答します。(オブザーバーモード)

(たとえば、現在画面に 3 つの UI が表示されており、各 UI にはプレーヤーの金額が表示されます。金額が変更されると、プロキシは対応する通知通知を送信し、3 つの UI が通知を受け入れて続行します。ビューアップデート)

2. メディエーターが他のメディエーターと頻繁に対話する必要がある場合、コマンドを使用して対話ステップを 1 か所で定義するのが良い方法です。

3. Mediator は、他の Mediator を直接取得して呼び出すことを許可されるべきではなく、Mediator でそのような操作を定義することは誤りです。上の概念図からわかるように、メディエーターとメディエーターの間に直接の通信は存在せず、結合を減らすという本来の目的に反します。

ビューへの変更が別のビュー コンポーネントに影響を与える場合は、通知通知を送信するだけです。

4. プロキシはステートフルです。状態が変化すると、通知を送信して Mediator に通知し、データの変更をビュー コンポーネントに反映します。

コマンドを通じて複数回使用されるこれらの「リクエスト」を実装すると、リクエストの独立性が高まり、再利用性が向上します。

プロキシ設計パターンとメディエータ設計パターン?

前に述べた 2 つの設計パターンは非常に似た処理を行いますが、定義上、プロキシは実際のデータを表すことと同等のデータ アクセスの制御に重点を置き、メディエーターはデータの対話 (カプセル化) (一連のオブジェクトの対話) に重点を置きます。 AB 間の対話の仲介者などの強力なロジックを使用する場合、UI との対話は比較的複雑で面倒なので、View での操作を処理するために Mediator が使用されます。

「Dahua Design Pattern」には、調停者、つまり国連や同様の環境保護団体を説明するための非常に良い例が示されています。私たちが日常的に連絡をとっている不動産業者は、調査、審査、販売、納税の責任を負っています。 、家の譲渡など (インタラクティブで強力なロジック) の作業。

家主に直接問い合わせをすると言われたら、知識が豊富であるだけでなく、法的なリスクも伴います。

もう 1 つの例は 4S ストアです。販売やアフターセールスなどのために 4S ストアに行きます。メディエーターでは、A と B が対話します。A と B の両方がメディエーター メディエーターを「知っています」。私たちは 4S ストアに行き、そして4S ストアが責任を負いますので、自動車メーカーにご相談ください。

コントローラーとコマンドとは何ですか?

コントローラーはすべてのコマンドのマッピングを保存します。コマンド クラスはステートレスであり、必要な場合にのみ作成されます。

ここでは、「リクエスト」と「動作」をオブジェクトにカプセル化し、論理部分を独立してカプセル化することで再利用性を高めるコマンド設計パターンを採用しており、ビューやメディエータを変更してもコマンド自体には影響しません。Facade のトップレベル インターフェイスを介して、プロキシ、メディエーター、およびコマンドは相互にアクセスし、通信できます。

コマンドは、プロキシ オブジェクトとメディエーター オブジェクトを取得して対話し、通知を送信し、他のコマンドを実行できます。アプリケーションの「起動」や「シャットダウン」など、複雑な操作やシステム全体の操作によく使用されます。アプリケーションのビジネス ロジックはここに実装する必要があります。

ファサードは起動時にコントローラーを初期化し、通知とコマンドの間のマッピングを確立する必要があります。

コントローラーは各通知をリッスンするように登録され、通知されると、通知に対応するコマンド クラスのオブジェクトをインスタンス化します。最後に、通知をパラメーターとして実行メソッドに渡します。詳細については、コマンド基本クラスの実装を参照してください。

つまり、Command の実行は、Notification 通知を送信することで実行されます。

コマンド オブジェクトはステートレスであり、必要な場合 (コントローラーが対応する通知を受信する) にのみ作成され、実行後に削除されます (実行メソッドが呼び出されます)。したがって、これらの寿命の長いオブジェクトでは Command オブジェクトを参照しないでください。

操作中に、コマンドを使用して Proxy と Mediator を初期化することができます。つまり、Facade に登録します。

例えば:

パブリック クラス ModelPrepCommand : SimpleCommand {

 //マクロコマンドによって呼び出されます

 public override void 実行 (INotification 通知) {

 IFacade.registerProxy (新しい SearchProxy ());

 IFacade.registerProxy (新しい PrefsProxy ());

 IFacade.registerProxy (新しい UsersProxy ());

 }

(ここではコマンド部分のスクリーンショットは掲載しません。モデルとメディエーターを全員が理解できれば、コマンド部分はより明確になります)

2 種類のコマンド:

Command は ICommand インターフェイスを実装します。PureMVC には、ICommand インターフェイスを実装する 2 つのクラス、SimpleCommand と MacroCommand があります。SimpleCommand には、Inotification インスタンスをパラメータとして受け入れる実行メソッドが 1 つだけあります。実際のアプリケーションでは、このメソッドをオーバーライドするだけで済みます。

MacroCommand を使用すると、複数のコマンドを順番に実行できます。実行ごとに Command オブジェクトが作成され、ソース通知への参照が渡されます。MacroCommand は、コンストラクターで独自の initializeMacroCommand メソッドを呼び出します。実際のアプリケーションでは、このメソッドをオーバーライドし、addSubCommand を呼び出してサブコマンドを追加する必要があります。SimpleCommand と MacroCommand を組み合わせて新しいコマンドを作成できます。

他に紹介するもの:

ビジネスロジック(ビジネスロジック)とドメインロジック(ドメインロジック)?
 

プログラム内にはコードを配置できる場所 (コマンド、メディエーター、プロキシ) が多数あるため、必然的に「どのコードをどこに配置する必要があるか?」という疑問が生じます。コマンドは正確に何をすべきでしょうか?

プログラム内のロジックはビジネスロジック(ビジネスロジック)とドメインロジック(ドメインロジック)に分けられますが、まず両者の違いを理解する必要があります。

ビジネスロジック(Business Logic)はモデルとビューステート(View)を連携させる必要があります。

モデルはプロキシを使用してデータの整合性と一貫性を保証します。プロキシはプログラムのドメイン ロジックを一元化し、データ オブジェクトを操作するための API を公開します。これは、データがクライアント側であるかサーバー側であるか、プログラムの他の部分に対するデータ アクセスが同期であるか非同期であるかに関係なく、データ モデル上のすべての操作をカプセル化します。

Mediator と Proxy は、Command から特定の操作の詳細を隠しながら、ViewComponent と Model (データ オブジェクト) を管理するために呼び出すいくつかの操作インターフェイスを Command に提供できます。

オブザーバーと通知しますか?

PureMVC の通信は、ゲーム開発のほぼすべての場所で使用されるデザイン パターンであるオブザーバー パターンを使用した疎結合方法で実装されています。非常に簡単な方法を使用して、プロキシ、メディエーター、コマンド、ファサードから送信するだけです。通知も必要ありません。通知インスタンスを作成する必要があります。

ファサードとプロキシは通知の送信のみ可能です。メディエータは通知の送信と受信の両方が可能です。通知はコマンドにマップされ、コマンドも通知を送信できます。これは、すべてのオブザーバーが同じ通知を受信する「パブリッシュ/サブスクライブ」メカニズムです。たとえば、複数の書籍および定期購読者が同じ雑誌を購読することができ、雑誌の新しい号が発行されると、すべての購読者に通知されます。

Facade は、コマンドと通知の間のマッピングを保存します。通知が発行されると、対応するコマンドがコントローラーによって自動的に実行されます。コマンドは複雑な対話を実装し、ビューとモデルの間の結合を軽減します。

通知定数を定義する

これらの通知名定数に他のプログラムからアクセスする必要がある場合、別の「ApplicationConstants」クラスを使用して、これらの通知名定数定義を保存できます。いつでも、Notification (通知) 名は定数として定義する必要があります。Notification を参照する必要がある場合は、その名前定数を使用します。これにより、コンパイル中に検出できないエラーを回避できます。コンパイラは定数をチェックできるため、文字列の場合は、誤って間違った文字列を入力した場合、コンパイラにはエラーを知る方法も報告する方法もありません。

調停者は通知を送信、宣言、受信します

Mediator が View に登録されると、Mediator の listNotifications メソッドが呼び出され、Mediator オブジェクトが扱うすべての通知が配列の形式で返されます。その後、システム内の他のロールが同じ名前の通知を発行すると、この通知を扱うメディエーターは handleNotification メソッドを呼び出し、通知をパラメーターとしてメソッドに渡します。

ここでは、メディエーターが通知者であり、プロキシ データが変更されると、メディエーターは通知を受け取り、UI を更新します。

プロキシは通知を送信しますが、受信しません

多くの状況で、プロキシは通知 (通知) を送信する必要があります。たとえば、プロキシがリモート サービスからデータを受信すると、通知を送信してシステムに通知します。または、プロキシのデータが更新されると、通知を送信してビュー コンポーネントに更新を通知します。 、など。

プロキシが通知 (notification) をリッスンすることも許可されている場合、ビュー (View) 層およびコントローラー (Control) 層との結合が高くなりすぎます。

ビューとコントローラーは、ユーザーがビジュアル インターフェイスを通じてプロキシが保持するデータと対話できるようにする責任があるため、プロキシによって送信された通知をリッスンする必要があります。ただし、ビュー レイヤとコントローラ レイヤへの変更はモデル レイヤに影響を与えるべきではありません。

最後に、ドキュメント内のビュー コンポーネントとメディエーターの間の対話の小さな例を示します。

フォームを備えた LoginPanel コンポーネントがあるとします。対応する LoginPanelMediator があり、LoginPanel と対話し、その入力情報に応じてログイン要求を送信します。

LoginPanel と LoginPanelMediator の連携は次のとおりです: ユーザーが情報の入力を完了し、ログインしようとすると、LoginPanel は TRY_LOGIN イベントを送信します。 LoginPanelMediator は、コンポーネントに含まれる LoginVO を「レポート本文」として通知を送信することで、このイベントを処理します。

ここでは LoginPanel.mxml 部分は省略されており、ビュー部分が異なります。

LoginPanel コンポーネントには、ユーザー フォーム入力を含む新しく作成された LoginVO オブジェクトが含まれています。ユーザーが「ログイン」ボタンをクリックするとイベントがトリガーされ、次の処理が LoginPanelMediator によって引き継がれます。

このように、View Component の役割は単純にデータを収集し、データ収集後にシステムに通知することです。改善できる点は、悪意のあるログインを避けるために、ユーザー名とパスワードの両方に内容がある場合にのみログイン ボタンを使用可能 (有効) にすることです。

View Component は内部実装を外部から隠します。Mediator によって使用される API 全体には、TRY_LOGIN イベント、LoginVO 属性、Panel の status 属性が含まれます。

最終的なまとめ:
 

View と Model の間には一方向の依存関係があり、View は Model が何であるかを認識する必要があり、View は Model データに基づいてビュー上のコンテンツも表示します。モデルはビューのコンテンツを気にしません。

プロキシとメディエーターは両方とも、その責任においてエージェントおよびメディエーターであり、他のコンポーネントとの通信を担当します。そして、その登録は次の方法で行われます。

一元管理のためのファサード。

プロキシとメディエーターには多くのビジネス ロジックを含めることはせず、ビジネス ロジック部分はコマンドで処理し、データ自体に対する一部の操作はプロキシとメディエーターに配置する必要があります。

Mediator では任意の Proxy にアクセスして変更できますが、これはお勧めできません。これらのタスクをコマンドに実行させて、View と Model 間の疎結合を実現します。こうすることで、コマンドをビューの他の部分で再利用できます。

 材料:

公式 GitHub 接続: https://github.com/PureMVC

PureMVC 公式 Web サイト: www.puremvc.org

ブログ: PureMVC 分析_Peter_Gao_ のブログ - CSDN blog_puremvc

ブログ: Unity での PureMVC フレームワークの適用 (1)_Peter_Gao_ のブログ - CSDN ブログ

おすすめ

転載: blog.csdn.net/qq_40097668/article/details/123987708