3

ソフトウェア設計に関する質問があります。いくつかの要素を含む Windows フォームがあり、顧客オブジェクトがあるとします。顧客は、たとえば、ビジネス、プライベート、または法人のいずれかです。

ここで、フォームで何が起こるかのすべての決定は、顧客のタイプによって異なります。たとえば、特定の要素が非表示になる、特定のラベル テキストが異なるなど、イベントの応答が異なります。

明らかに、これをコーディングする 1 つの方法は、決定を下す必要があるたびに CASE ステートメントを使用することです。もう 1 つの方法は、Customer クラスと、BusinessCustomer、PrivateCustomer、CorporateCustomer などの他の 3 つのクラスを基本クラスから継承させることです。後者の場合、疑問が生じます。どのようにしてウィンドウをそこに組み込むのでしょうか....

編集済み

フォーム内にフォームを埋め込むことはできますか? 私の要件では、一度に 2 つのウィンドウを表示する必要はありません。そのため、MDI を使用する必要はありません。しかし、ここでいくつかの ppl のコメントに基づいて設計を簡素化するために、3 つの異なる顧客フォームを維持し、その場でメイン フォーム内に埋め込みたいと考えています。そうすれば、3 つの GUI が分離され、すべてのコントロールの可視性に対処する必要がなくなります。

次のように、フォームを別のフォームに追加できると仮定しています。

Form child_form = new Form();
parent_form.Controls.Add(child_form);
4

6 に答える 6

2

これらの決定は、実際には GUI で行うべきではありません。これらの決定を行い、単体テストを作成する GUI の背後に ViewModel が必要です。(または、Presenter、または Controller -- 異なる名前はすべてほぼ同じことを意味します。GUI クラスから決定を取得し、単体テストできるものにします。)

次に、ViewModel には、たとえば、GUI が無効にする各要素のブール型プロパティと、実行できる各アクションのメソッド (CloseCustomerAccount() など) があります。

フォームが特定のタイプの顧客用に作成され、フォームの存続期間中に顧客が別のタイプの顧客に変更されない限り、Customer オブジェクト (実際の顧客データをすべて格納する) を渡すことができます。 ) を ViewModel のコンストラクターに渡してから、ViewModel を Form のコンストラクターに渡します。フォームは、InitializeComponent() を呼び出した直後に、すべての Enabled プロパティを設定できます。一方、顧客タイプが変更される可能性がある場合、ViewModel はフォームがフックするいくつかのイベントを公開する必要があるため、フォームは有効化ロジックをいつ再実行するかを認識します。

次に、質問がフォームからビューモデルに移動します。一連の case ステートメントを持つ 1 つの ViewModel クラス、またはポリモーフィズムを使用する 3 つの ViewModel クラス (おそらく 4 番目は基本クラス) と、特定の顧客に基づいてどの ViewModel クラスをインスタンス化するかを決定するファクトリ メソッドがありますか? ?

あなたのコードをガイドにしましょう。おそらくケースステートメントである最も単純なアプローチから始めます。関心のあるすべての動作の単体テストを作成します。ケース ステートメントがぎこちなくなり始めた場合は、顧客の種類ごとに ViewModel の子孫を追加し、ケース ステートメントを仮想メソッドに抽出し始めます。リファクタリング中に間違いを犯した場合、テストはあなたを捕まえます。

于 2009-04-29T22:39:03.747 に答える
1

3 つの異なるウィンドウがあり、それぞれが特定のタイプの顧客を処理している場合、基本クラスまたはコントラクトを操作してもあまり意味がありません。ただし、顧客クラスを取り、使用する正しい画面を決定するファクトリ クラスを使用すると、スマートになる可能性があります。

私はこれにかなり遭遇しました。最終的には、一般的なものを処理するベース ウィンドウを作成し、具象型ごとに拡張します。

于 2009-04-29T22:22:26.033 に答える
1

Joshua Beldenの答えに同意します。さまざまな種類の顧客に対応する 3 つの個別のフォームは、維持するのがおそらく最も簡単です。

また、まだご存じない方のために説明すると、Form クラスから派生させて、派生 Form クラスで微調整することもできます。これは、デザイナーによってもサポートされています。

ただし、代替手段を提供したいと思います。

ブリッジ パターン: 抽象化をその実装から分離して、2 つが独立して変化できるようにします。

あなたができることはこれです:

UIImplementation3 つの個別のクラスを作成します。これらのクラスは、UI とCustomerフォームのイベントを微調整できます。フォームのプライベート メンバーにアクセスするには、クラスがクラスUIImplementation内にネストされていることを宣言する必要がありますCustomerForm。(部分クラスを使用して、これらを異なるファイルに分けます)。フォーム自体が重要で、微調整が重要でない場合、これは適切なオプションです。言うのは難しいです。

于 2009-04-29T22:57:03.673 に答える
0

いくつかの抽象 Customer インターフェイスを実装する 3 つのクラスに進みます。アプリでは、Customer 型の変数customerがあり、特定の Customer 型のオブジェクトがそこに格納されます。GUI は、どの顧客が実際に GUI と対話するかに関係なく、インターフェイスに依存して顧客変数のメソッドを呼び出すことができます。

この記事をご覧ください。

于 2009-04-29T22:23:28.403 に答える
0

ソリューションは、コードではなくデータによって駆動される必要があります。

したがって、さまざまなコントロールに状態 "A"、"B"、または "C" で表示されるタグを付けると、1 つのメソッドでその状態を調べて、どのコントロールを表示するかどうかを判断できます。

状態 "D" の新しいコントロールを追加するときに、コントロール自体を追加するために必要なコード変更以外は、コードを変更する必要がないことを知っています。

また、フォームを共有、サブフォーム a、サブ b の 4 つのサブフォームに分割し、「共有」と「サブ a」の両方を親フォームに一緒に表示することも検討してください。

于 2009-04-29T23:01:34.677 に答える
0

私は MVP 型のアプローチを採用し、バインディングを介して UI コントロールの有効/無効状態を導出するブール型プロパティを公開する CustomerPresenter クラスを定義します。

public class CustomerPresenter
{
  private Customer _customer;

  public CustomerPresenter(Customer customer)
  {
    _customer = customer;        
  }

  public bool EnableUI
  {
     get
     {
       //TODO: put your customer type basic logic here (switch statement or if/else)
       return _customer.Type == CustomerType.Business;
     }
  } 
}

public CustomerForm: WinForm
{
   private CustomerPresenter _customerPresenter;

   public CustomerForm(){};

   public CustomerForm(Customer customer)
   {
      _customerPresenter = new CustomerPresenter(customer);
   }      

   private void CustomerForm_Load(object sender, EventArgs e)
   {
      _someButton.DataBindings.Add("Enabled",_customerPresenter,"EnableUI");
   }

} 
于 2009-04-29T22:54:00.123 に答える