I have a design that I am working on and wanted to be clear on how one should handle multiple implementations of an interface using MVP pattern. Here is my situation:
There is a base "Tank" interface which defines basic functionality of what a tank should do.
public interface ITankView
{
public string TankName
public double TankLevel
public double TankSize
... ext ...
}
My presenter accepts implementations of this interface (i.e. - the "Tank" view):
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;
}
}
I also have multiple implementations of the ITankView interface:
// 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;}
}
So my question is how do I handle the "Advanced" MixingTankView in the TankPresenter while adhering to the MVP patter and best practice?
For example, if I instantiate the TankPresenter with a MixingTankView how would you access the special "Advanced" functionality?
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!!
}
}
I'm thinking I would need to add in a presenter for each and every type of Tank. So in this example that would be a IBasicTankPresenter and a IMixingTankPresenter but I'm still a little confused on how that would work. Also 90% of the functionality between the two tanks is identical so it seems redundant. In reality I have more than just 2 tanks and the actual implementation is much more complex but each tank type only has slight differences.
My Goals are:
First, you will need to add an interface for the MixableTankView -
public interface IMixableTankView : ITankView
{
double MixingSpeed {get;set;}
}
Then, you can simply use generics. You start with your basic presenter, only now you change the ITankView
to a type parameter:
public class TankPresenter<TTankView> where TTankView : ITankView
{
TTankView tank;
// basic implementation here
}
and add another presenter that inherits it:
public class MixingTankPresenter : TankPresenter<IMixableTankView>
{
// IMixableTankView special implementation here
}
You do this for every different implementation of the ITankView
- This way, most of the code will still be only in the base TankPresenter
, and you get to keep MVP principles throughout your project.