MVP中Presenter的实现问题

时间:2010-08-14 13:54:16

标签: c# .net oop mvp

所以..我打算使用模型视图展示器(“被动”模式,其中UI非常愚蠢并将所有事件发送到Presenter,并且Presenter负责处理模型)以粘合我的域名的业务逻辑和用户界面。

我的问题是我的演示者应该怎么样。这是我想要的吗?

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

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

    ...
}

我应该通过构造函数注入传递预期ITicTacToeView的实例吗?这将允许我将这个TicTacToeGamePresenter类与Forms,WPF,WebForms等一起使用。我只需要确保我的View实现了ITicTacToeView接口。

或者我应该直接实例化我打算直接使用的具体类,并且只有一个无参数构造函数?这似乎有点无意义,但我不得不问:(。

我目前将ITicTacToeView接口定义为:

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

还有一件事。在对TicTacToeGamePresenter的构造函数进行编码时,我最终得到了这个:

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);
}

现在,在查看代码之后,我认为通过将“类以上”赋予类实例化的责任,可能会更好地使这个类依赖性更明确:

    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;
    }

哪一个更好? 感谢

2 个答案:

答案 0 :(得分:1)

我会选择你的第一个选项:使用构造函数将视图注入到演示者中,因为它允许你支持不同类型的UI,前提是它们都实现了界面。

此外,从单元测试的角度来看,您的生活将变得更加简单,因为任何实现该接口的模拟类都可用于您的测试

编辑:添加了WCSF如何做的代码示例 WCSF使用依赖注入,并且每个视图都具有注入视图的演示者的属性。这也适用,并且不需要构造函数方法,但这需要公开的View属性公开。

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

答案 1 :(得分:1)

我认为您没有太多选择但是使用构造函数(或参数)注入。

在运行时,您的视图在其演示者首次实例化时已经被实例化;如果您在演示者中创建视图,那么您将使用视图的单独实例,并且不会处理任何您期望的事件。


如果您使用IoC container创建演示者,我会倾向于使用构造函数的第二种方法。如果你不是,那么你要求你的观点代表演示者实例化IPlayers,PlayerControllers和Games,它可能不应该知道如何做到这一点。 Take a look here讨论了为什么要使用IoC容器。