誰もが言っているように、多数の意見がありますが、それらのどれも正しいものでも間違っているものでもありません。無数のパターンに入ることなく、MVPのみに焦点を当てることなく、実装に関するいくつかの提案があります。
それらを分離してください。ビューは、ビューとプレゼンターの間の結合を形成するインターフェースを実装する必要があります。ビューはプレゼンターを作成し、プレゼンターに自身を挿入し、プレゼンターがビューと対話するために提供するメソッドを公開します。ビューは、これらのメソッドまたはプロパティを任意の方法で実装する責任があります。通常、ビューは1つ、プレゼンターは1つですが、場合によっては、1つのプレゼンター(Web、wpfなど)という多くのビューを使用できます。ここで重要なのは、プレゼンターがUIの実装について何も知らず、インターフェイスを介してビューとのみ対話することです。
以下に例を示します。最初に、ユーザーにメッセージを表示する簡単なメソッドを持つビュークラスがあります。
interface IView
{
public void InformUser(string message);
}
これがプレゼンターです。プレゼンターはIViewをコンストラクターに取り込むことに注意してください。
class Presenter
{
private IView _view;
public Presenter(IView view)
{
_view = view;
}
}
次に、実際のユーザーインターフェイスを示します。これは、ウィンドウ、ダイアログ、Webページなどです。重要ではありません。ビューのコンストラクターは、自身に注入することでプレゼンターを作成することに注意してください。
class View : IView
{
private Presenter _presenter;
public View()
{
_presenter = new Presenter(this);
}
public void InformUser(string message)
{
MessageBox.Show(message);
}
}
プレゼンターは、ビューが実行するメソッドをビューがどのように実装するかを気にしません。プレゼンターが知っている限り、ログファイルへの書き込みであり、ユーザーに表示することさえできません。
いずれにせよ、プレゼンターはバックエンドでモデルを使用して何らかの作業を行い、ある時点で何が起こっているかをユーザーに通知したいと考えています。そのため、プレゼンターのどこかにビューInformUserメッセージを呼び出すメソッドがあります。
class Presenter
{
public void DoSomething()
{
_view.InformUser("Starting model processing...");
}
}
これがデカップリングを取得する場所です。プレゼンターは、IViewの実装への参照のみを保持し、実際に実装方法を気にしません。
また、ビューでプレゼンターへの参照があり、オブジェクトがコンストラクターを介して設定されるため、これも貧弱な実装です。より堅牢なソリューションでは、おそらく、Windsor、Ninjectなどの制御の反転(IoC)コンテナーを調べて、実行時にオンデマンドでIViewの実装を解決し、それをさらに分離することをお勧めします。