如何使用 MVP 模式处理不同的接口实现?

How to handle different interface implementations using MVP pattern?

我有一个正在进行的设计,我想弄清楚应该如何使用 MVP 模式处理一个接口的多个实现。这是我的情况:

有一个基础 "Tank" 界面,它定义了坦克应该做什么的基本功能。

public interface ITankView
{
  public string TankName
  public double TankLevel
  public double TankSize
  ... ext ...
}

我的演示者接受此接口的实现(即 - "Tank" 视图):

public class TankPresenter
{
  ITankView tank;
  public void TankPresenter(ITankView tank)
  {
    this.tank = tank;
  }

  public void DoStuffWithaBasicTank()
  {
     tank.TankName = "This is a basic Tank!"
     tank.TankSize = 100;
     tank.TankLevel = 50;
  }
}

我还有 ITankView 接口的多个实现:

// Just a basic tank with a level:
public class BasicTankView, ITankView
{
   public string TankName {get; set;}
   public double TankLevel {get; set;}
   public double TankSize {get; set;}
}

// The "Advanced" version of a tank:
public class MixableTankView, ITankView
{
   public double TankName {get; set;}
   public double TankLevel {get; set;}
   public double TankSize {get; set;}
   public double MixingSpeed {get; set;}
}

所以我的问题是如何在遵守 MVP 模式和最佳实践的同时处理 TankPresenter 中的 "Advanced" MixingTankView?

例如,如果我用 MixingTankView 实例化 TankPresenter,您将如何访问特殊的 "Advanced" 功能?

public MixingTankView view = new MixingTankView();
public TankPresenter Presenter = new TankPresenter(view );


public class TankPresenter
{
  ITankView tank;
  public void TankPresenter(ITankView tank)
  {
    this.tank = tank;
  }

  public void DoStuffWithaMixingTank()
  {
     tank.TankName = "This is a mixing Tank!"
     tank.TankSize = 100;
     tank.TankLevel = 50;
     tank.MixingSpeed = 75; // This does not work as it's not declared in ITankView!!
  } 
}

我想我需要为每种类型的坦克添加一个演示者。因此,在此示例中,这将是一个 IBasicTankPresenter 和一个 IMixingTankPresenter,但我仍然对它的工作方式感到困惑。此外,两个坦克之间 90% 的功能是相同的,因此看起来是多余的。实际上,我有不止 2 个坦克,实际实施要复杂得多,但每种坦克类型只有细微差别。

我的目标是:

  1. 减少代码复杂度和 coupling/inter-dependance 代码
  2. 在某种程度上坚持 MVP 模式
  3. 不重复了 每种坦克类型都有很多次。
    • 为了自己的理智,我想减少代码量
    • 我真的需要为每 1 个坦克视图配备 1 个演示者吗?

首先,您需要为 MixableTankView 添加一个界面 -

public interface IMixableTankView : ITankView
{
    double MixingSpeed {get;set;}
}

然后,你可以简单地使用泛型。您从基本的演示者开始,只是现在将 ITankView 更改为类型参数:

public class TankPresenter<TTankView> where TTankView : ITankView
{
    TTankView tank;
    // basic implementation here
}

并添加另一个继承它的演示者:

public class MixingTankPresenter : TankPresenter<IMixableTankView>
{
    // IMixableTankView special implementation here
}

你对 ITankView 的每个不同实现都这样做 - 这样,大部分代码仍然只在基础 TankPresenter 中,你可以在整个项目中保持 MVP 原则.