开发者

Implementation question of the Presenter in MVP

开发者 https://www.devze.com 2023-01-11 08:00 出处:网络
So..I intend to use a Model View Presenter(the \"passive\" mode, in which the UI is pretty dumb and sends all the events to the Presenter, and the Presenter takes care of dealing with the Model) to gl

So..I intend to use a Model View Presenter(the "passive" mode, in which the UI is pretty dumb and sends all the events to the Presenter, and the Presenter takes care of dealing with the Model) to glue my domain's business logic and the UI.

My question is how should my Presenter look like. Is this what I want?

public class TicTacToeGamePresenter
{
    private readonly ITicTacToeView view;
    private readonly PlayerController model;

    public TicTacToeGamePresenter(ITicTacToeView view) {
        this.view = view;
    }

    ...
}

Should I by constructor injection pass the instance of the intended ITicTacToeView? This would allow me to use this TicTacToeGamePresenter class with Forms, WPF, WebForms, etc. I would only have to make sure my View implements the ITicTacToeView interface.

Or should I just instantiate the kind of concrete classes I intend to use directly and just have a parameterless constructor? Th开发者_开发技巧is seems kinda pointless, but I had to ask :( .

I currently have the ITicTacToeView interface defined as:

public interface ITicTacToePassiveView
{
    event EventHandler<EventArgs<Point>> ButtonClicked;
    void PlayerOPlayed(Point location);
    void PlayerXPlayed(Point location);
    void EnableStartButton();
    void DisableStartButton();
}

One more thing. When coding the constructor of TicTacToeGamePresenter I ended up with this:

public TicTacToeGamePresenter(ITicTacToePassiveView view)
{
    this.view = view;

    IGameLogicAnaliser gameLogicAnaliser = new GameLogicAnaliser();
    IPlayer playerO = new Player(gameLogicAnaliser);
    IPlayer playerX = new Player(gameLogicAnaliser);

    Game game = new Game(playerO, playerX);

    this.playerOModel = new PlayerController(playerO, game);
    this.playerXModel = new PlayerController(playerX, game);
}

Now, after looking to the code I reckon that maybe it'd be better to have this' class dependencies be made more explicit by giving the "class above" the responsability of class instantiation:

    public TicTacToeGamePresenter(ITicTacToePassiveView view, IPlayer playerO, IPlayer playerX, Game game, PlayerController playerOModel, PlayerController playerXModel)
    {
        this.view = view;
        this.playerO = playerO;
        this.playerX = playerX;
        this.game = game;
        this.playerOModel = playerOModel;
        this.playerXModel = playerXModel;
    }

Which one would be better? Thanks


I would go with your first option : using the constructor to inject the view into the presenter as it will allow you to support different types of UI provided they all implement the interface.

Also, from a unit testing perspective, your life will be much simpler as any mock class implementing that interface can be used for your testing

EDIT: Added code sample from how WCSF does it WCSF uses dependency injection and every view has a property for the presenter that is injected into the view. This works just as well and there is no need for the constructor approach but this will need a public View property exposed.

[CreateNew]
public DefaultViewPresenter Presenter
{
    set
    {
        this._presenter = value;
        this._presenter.View = this;
    }
}


I don't think you have much choice BUT to use constructor (or parameter) injection.

At runtime, your view will already be instantiated when its presenter first instantiates; if you create the view in the presenter, then you'll be working with a separate instance of your view, and none of the events you'll expect will be handled.


If you're using an IoC container to create your presenter, I'd favor the second approach to your constructor. If you're not, then you're asking your view to instantiate IPlayers, PlayerControllers and Games on behalf of the presenter, and it probably shouldn't know how to do that. Take a look here for some discussion on why you'd want to use an IoC container.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号