7

スイングアプリケーションでMVCパターンを適用しようとしています。ただし、パネルの階層がネストされていることを考えると、2つの大きな問題に直面しています。たとえば、親->子->孫->孫孫です。

問題1:このような階層がある場合、コントローラーとビューの間でデータを転送するにはどうすればよいですか?親から子にデータを渡していくと、多くの重複が発生し、1人の子を変更すると、すべての親に変更が必要になります。ビューがdbからのデータに直接アクセスすることを望まず、データがコントローラーのみを介してビューに転送されることを望みます。

問題2:そのような階層でビューからコントローラーにイベントを伝播する方法は?PropertyChangeListenerの使用を考えています。コントローラがアクションを実行する必要がある場合、ビューはPropertyChangeイベントを起動します。コントローラはこれらのイベントをリッスンし、何らかのアクションを実行します。しかし、階層に対してこれを行うと、コードが重複します。

役立つアイデアが3つあります。

  1. パネルごとにコントローラーを使用しますが、このようにすると、コントローラーがたくさんなります。
  2. ビューとコントローラー間の通信を提供するMediatorデザインパターンを使用します。
  3. ビューからすべてのプロパティ変更イベントをリッスンし、関心のあるコントローラーに通知するCentral Reciever&Notifierを使用します。しかし、これは私の2番目の問題を解決するだけです:

下の図を参照して、3番目のアイデアの写真を入手してください。2つ目はメディエーターが中心になります。

誰かがそのような問題をより良い方法で実装したかどうかを評価して知らせてください。

ここに画像の説明を入力してください

4

3 に答える 3

1

問題1:このような階層がある場合、コントローラーとビューの間でデータを転送するにはどうすればよいですか?親から子にデータを渡していくと、多くの重複が発生し、1人の子を変更すると、すべての親に変更が必要になります。ビューがdbからのデータに直接アクセスすることを望まず、データがコントローラーのみを介してビューに転送されることを望みます。

階層を無視して、関連するコントローラーにビューを登録することで、より直線的なアプローチをとるのはどうですか?Observerデータは、またはListenerパターンを介して変更がトリガーされるモデルを介して取得できます。

これにより、重複が発生することはありません。すべてが1つのモデルまたは一連のモデルに集中化されます。1つまたは複数のコントローラーは、ユーザーアクションまたは外部イベントが発生した後、登録されたビューのリストに対して通知を実行できます。

また、あなたが言うように、ビューは間違いなくデータソースにアクセスするべきではありません。ここには少なくとも1つの抽象化レイヤーが必要です。コントローラーがメディエーターパターンを使用している場合、私が行うことは、追加のデータレイヤーのインターフェイスにリクエストを転送することでこれを処理することです。

さらに考えてみると、ビューで登録してもらうのはいい考えではないと思います。だから私はこれを別にしておくでしょう。手作業でビューを初期化するか、必要なビューを反復処理する方法を見つけます。おそらく、このステップを自動化する一種のファクトリを通してあなたの意見を得るでしょう。

問題2:そのような階層でビューからコントローラーにイベントを伝播する方法は?PropertyChangeListenerの使用を考えています。コントローラがアクションを実行する必要がある場合、ビューはPropertyChangeイベントを起動します。コントローラはこれらのイベントをリッスンし、何らかのアクションを実行します。しかし、階層に対してこれを行うと、コードが重複します。

ここでも、線形アプローチを採用できます。ビューが登録されると、コントローラーはそのビューにリスナーを追加できます。または、ディスパッチメカニズムを介して処理できるセマンティックスタイルメッセージ(例:doAction( "Save"))をビューに送信させることもできます。パラメータを転送する方法を決定する必要があります。

PropertyChangeListenersが必要ですか?つまり、そのような粒度が必要ですか?

役立つアイデアが3つあります。

パネルごとにコントローラーを使用しますが、このようにすると、コントローラーがたくさんなります。ビューとコントローラー間の通信を提供するMediatorデザインパターンを使用します。ビューからすべてのプロパティ変更イベントをリッスンし、関心のあるコントローラーに通知するCentral Reciever&Notifierを使用します。しかし、これは私の2番目の問題を解決するだけです:

これは漠然とHMVCのように聞こえます。このアプローチでは、サブシステムごとに3つのmodel-view-controllerがあります。これは興味深いアイデアですが、面倒な場合があり、階層がどのように機能するのか、調整/従属がどのように達成されるのかが明確ではありません。

おそらく、アプリのモジュール/サブシステムごとに4番目のニュートラルクラスを設定して、ビュー、モデル、コントローラーのいずれかが欠落しているか正しくない場合に例外をスローしてプラグインすることができます。

または、中央通知機能のこの考え方に従って、中央コントローラーを他の機能固有のコントローラーまたはより基本的なアクションへのルーティングメカニズムとして機能させることができます。メッセージがこれらにどのように再ルーティングされるかはあなた次第です。集中化によりこのクラスの設計が不可欠になるため、スレッド化に注意してください。

何をするにしても、物事をできるだけシンプルにするようにしてください。モデルとコントローラーを上げた状態で、大騒ぎせずにテストビューを表示できるはずです。

于 2013-03-18T22:40:12.930 に答える
1

問題 1 について提案があります。

別のビュー モデルのプロパティを含むビューモデルを持つことができます。また、モデル バインダーがすべてのプロパティをバインドするため、コントローラー メソッドでは親の ViewModel を受け取るだけで済みます。

public class GrandChildViewModel{
    public Int32 SelectedDropDownItem { get; set; }
    public List<Foo> ListOfFoo { get; set; }
}

public class ChildViewModel{
    public String Name { get; set; }
    public Int32 Age { get; set; }
}
public class FatherViewModel{
    public ChildViewModel Child { get; set; }
    public GrandChildViewModel GrandChild { get; set; }
}

これは階層の例です。ビューはFatherViewModelのみを参照します。また、コントローラーはFatherViewModelも受け取ります。次のような HTML を作成すると、modelBinder は自動的にその役割を果たします。

@Html.TextBoxFor(m => m.Child.Name)

入力をレンダリングします:

<input type="text" id="Child_Name" name="Child_Name" />
于 2013-03-18T15:43:08.240 に答える