My concrete classes can be one of the type permutations shown below. But, since I cannot inherit from two classes (case 4 and 5) I had to convert one of them to interface which introduce code duplication shown in FIX section below. I know someone will say "use composition", but I don't see how to change the design to take this into account.
Type permutations:
ControllerSimulator
MovingControllerSimulator
RegistersControllerSimulator
ControllerSimulator
+RegistersControllerSimulator
MovingControllerSimulator
+RegistersControllerSimulator
CODE
public abstract class ControllerSimulator
{
protected virtual void OnTurningOn() { }
public void TurnOn()
{
...
}
protected virtual void OnTurningOff() { }
public void TurnOff()
{
...
}
// more base methods
...
}
public abstract class MovingControllerSimulator : ControllerSimulator
{
public virtual void Disable() { }
public void SetMotionDuration(TimeSpan duration)
{
_motionDuration = duration;
}
protected void OnMoveStarted()
{
MoveStarted?.Invoke();
}
// more base methods
...
}
public abstract class RegistersControllerSimulator : ControllerSimulator
{
protected Dictionary<string, object> Registers;
protected abstract void OnRegisterChanged(string regName, object regVal);
public void UpdateRegister(string regName, object regVal)
{
Registers[regName] = regVal;
OnRegisterChanged(...);
}
// more base methods
...
}
FIX
Since I cannot inherit from two classes I decided to convert RegistersControllerSimulator
to an interface and create RegistersMovingControllerSimulator
and RegistersNonMovingControllerSimulator
. But, this requires code duplication which I potentially can solve by moving it to utils.
interface IRegistersControllerSimulator
{
void UpdateRegister(string regName, object regVal);
}
public abstract class RegistersMovingControllerSimulator : MovingControllerSimulator, IRegistersControllerSimulator
{
protected Dictionary<string, object> Registers;
protected abstract void OnRegisterChanged(string regName, object regVal);
public void UpdateRegister(string regName, object regVal)
{
Registers[regName] = regVal;
OnRegisterChanged(...);
}
}
public abstract class RegistersNonMovingControllerSimulator : ControllerSimulator, IRegistersControllerSimulator
{
protected Dictionary<string, object> Registers;
protected abstract void OnRegisterChanged(string regName, object regVal);
public void UpdateRegister(string regName, object regVal)
{
Registers[regName] = regVal;
OnRegisterChanged(...);
}
}
public class Concrete_Registers_Moving_Controller : RegistersMovingControllerSimulator
{
// Uses "await Task.Delay(_motionDuration)" to imitate motion
}
public class Concrete_Registers_NonMoving_Controller : RegistersNonMovingControllerSimulator
{
}
public class Concrete_NonRegisters_Moving_Controller : MovingControllerSimulator
{
// Uses "await Task.Delay(_motionDuration)" to imitate motion
}
public class Concrete_NonRegisters_NonMoving_Controller : ControllerSimulator
{
}
Aucun commentaire:
Enregistrer un commentaire