1

フォームとロジック クラスがあります。ユーザーのアクションに基づいて、クラスはアクションのリストを生成します。これらのアクションは、ユーザーが選択できるように、フォーム上にボタンとして表示する必要があります。私の最初の解決策はこれでした:

public class Logic {
    public List<string> GetActions() {
        List<string> result = new List<string>();
        // ...prepare list
        return result;
    }
}

public class FrmGUI : Form {
    Logic logic = new Logic();
    private void PopulateButtons() {
        foreach(string action in logic.GetActions(){
            //...create button
        }
    }
}

GUI は Logic クラスから文字列のリストを取得し、それを使用してパネルにボタンを配置します。Logic クラスの動作について何かを公開しているため、これはおそらく OO の悪習です。ここでは、GetActions メソッドが常に存在し、Logic クラスが常にこの文字列のリストを返すことができるという前提があります。

別の解決策はこれです:

public class Logic {
    public void PopulateButtons(Panel panel, Action<object, EventArgs> eventHandler) {
        // ...prepare list
        // ...populate buttons
    }
}

public class FrmGUI : Form {
    Logic logic = new Logic();
    private void PopulateButtons() {
        logic.PopulateButtons(this.panel1, actionButtonClickHandler);
    }
}

ここで、GUI クラスはロジック クラスについて何も認識せず、ボタンが読み込まれることだけを期待しています。一方、ロジック クラスは現在、GUI に関与しています。

そのような場合を処理する正しい方法は何ですか。または、より優れた 3 番目の実装があります。

4

6 に答える 6

2

前者のパターンを使用します。ロジック層が情報を作成し、UI 層がその情報を使用して UI を作成します。

そうすれば、項目のドロップダウン リストを使用するために UI のスキンを変更することにした場合、ロジックではなく UI レイヤーのみを変更する必要があります。

これは、UI レイヤーがロジック レイヤーによって提供される型/データに最小限の依存関係を持っていることを意味します (ロジックがどのように実装されているかについて何も知らない限り、それは問題ありません) が、ロジック レイヤーはまったくわかりません。 UI 実装とは何かについて - これはあなたが望むものです (システム内の下位レベルのコンポーネントは、上位レベルの設計について何も知らない必要がありますが、上位レベルのコンポーネントは、使用する下位レベルのコンポーネントの基本的な理解を必ず持っている必要があります)。 )。

UI 自体がロジックを作成するのではなく、アプリケーション (またはその他の外部エンティティ) がロジックと UI の両方を作成し、それらをリンクすることが望ましいでしょう。これにより、UI とロジックをより疎結合にすることができます。

于 2012-09-14T11:42:45.360 に答える
1

Logicあなたとあなたの間に抽象化のレイヤーを配置することをお勧めしますFrmGUI

単純な例として、アプリケーションにログインがあるとします。論理画面のインターフェースを定義します。ここでは、どのコントロールが使用されているかについては言及されていないことに注意してください。ロジック クラスは、使用される UI クラス/フォームを認識しません。

interface ILoginScreen : IScreen
{
   event EventHandler LoginInvoked;
   event EventHandler CancelInvoked;

   string User { get; set; }
   string Password { get; set; }   
}

LoginLogic クラスには、次のようなコードがあります。

void Start() // initial LoginLogic method
{

   ILoginScreen loginScreen = uiFactory.CreateLoginScreen();

   loginScreen.User = string.empty;
   loginScreen.Password = string.empty;

   loginScreen.LoginInvoked += new EventHandler(LoginScreen_LoginInvoked);
   loginScreen.CancelInvoked += new EventHandler(LoginScreen_CancelInvoked);

   loginScreen.Show();

}

void LoginScreen_LoginInvoked(s, e)
{
   if (ValidateCredentials(loginScreen.User, loginScreen.Password))
   {
      // goto the next screen logic controller
   }
}

フォームに ILoginScreen を実装し、UI フィールドを USer プロパティと Password プロパティのデータで更新します。さらに、ユーザーのフィードバック (ボタンのクリック、Escape キーストロークなど) に基づいて、必要な Login および Cancel イベントを発生させます。

これは単純な例ですが、私は多くの Windows Mobile および Windows CE アプリを実行しており、同じアプリケーションを非常に異なるフォーム ファクターの OS バリアントで実行することが非常に一般的であり、このアプローチにより文字通り新しい GUI フォームにスナップすることができます。要因。その使用法の中心は、適切な UI 実装を提供するために動的にロードされる UIFactory です。

于 2012-09-14T17:58:51.057 に答える
1

それLogicがサポートするアクション (1 番目のパターン) を報告することができます (ただし、戻り値の型はGetActions実際IEnumerable<string>にはリストの代わりにする必要があります)。

Not so good is that in your sample the form instantiates the Logic class directly. Typically, you'd create an interface or abstract base class for the different types of Logic classes that you might have, and have concrete implementations fill in the functionality. The form would then get the logic to use through some inversion-of-control mechanism.

于 2012-09-14T11:41:55.393 に答える
1

正しい?????何年にもわたって、多くの人々がこのアプローチを標準化しようと多くの時間を費やしてきましたが、その答えは UI デザイン パターンの数から導き出されるかもしれません。

現時点で流行している MVC、MVP、MVVM パターンを確認することをお勧めします。

一般に:

プレゼンテーションからロジックを分離しようとするのは良い考えです。そうすれば、正しい方向に進むことができます。ただし、この分割の結果の 1 つは、"ロジック" がプレゼンテーションについて何も知らない方がよいということです (それを担当するクラスが既にあるため)。

したがって、「ボタン」の概念について考え、(論理的な観点から)「本当にコマンドのことではないのか?」と考える必要があるかもしれません。画面のコンテキストで考えたときにのみ、実際にボタンになります。しかし、たとえば、特定の銀行口座にトランザクションをロードするコマンド....これがどのように機能するかを概念化するための画面は必要ありません。

私が見つけた良いことは、フォーム フロント エンドと、まったく同じことを行う Web フロント エンドの両方でこのアプリを開発しようとしていると想像することです。明らかに、これら 2 つのアプリのプレゼンテーション レイヤーは、根本的に異なるテクノロジが使用されているため、まったく異なります。

しかし、コードを 2 回書きたくないので、できるだけ多くの共通コードを詰め込む「ロジック」層も用意します。たとえば、銀行口座が引き落とされているかどうかを判断する - Web であるか勝ちであるかは問題ではありません。逆に、Web と Win で異なるコードを書くことになる場所はすべて、「プレゼンテーション」レイヤーに属します。たとえば、超過残高を赤で表示します。

思考の糧。

于 2012-09-14T11:57:15.703 に答える
0

GUIとロジックの間のインターフェースは単なる文字列のリストであるため、最初のものの方が優れています。その後、それはすべて、ボタンからロジッククラスのアクションを呼び出す方法によって異なります。アクション文字列を実行するジェネリックメソッドがある場合は、問題ありません。アクション文字列に応じてロジッククラスで異なるメソッドを呼び出す必要がある場合は、アクション文字列とメソッド呼び出しをマッピングするためにGUIクラスでマッピングする必要があります。この「アクション文字列-マッピングメソッド」をロジッククラスからインポートして、物事を分離しておくこともできます。

于 2012-09-14T11:44:50.747 に答える
0

私の意見では、ロジック層や GUI 層などを作成する理由によって異なります。最も一般的な理由は、ロジックを再利用することです。たとえば、ロジックを WPF や Web GUI に使用したり、GUI に送信する前にデータを処理する必要があります。最初の例は、前述のパターンに適合します。2番目の例では、GUI固有であるため、ロジックは再利用できないようです。しかし、現実の世界では、それが正しいか間違っているかの答えがあります。アーキテクチャはニーズに適合し、プロジェクトを保守可能にする必要があります (例: 冗長なコードを削減するなど)。あなたの場合、質問は次のとおりです。これらの機能が必要な頻度と、いつどこで必要ですか?

于 2012-09-14T12:05:17.617 に答える