I have a scenario where multiple concrete classes extends
multiple Abstract
classes. I am at a loss to come up with a clean structure, reduce the number of files and avoid code repetition.
The ask is to display various sensor values in different ways based on some criteria. Sensor values like temperature, voltage, current etc can have an anlaog widget, a numeric label or a combination of both. I have 3 Abstract
classes for the 3 different kind of views. These 3 Abstract
classes implement a method that defines how the view is to be drawn. Each sensor view extends
the 3 Abstract
classes and implements methods to read the sensor, perform some engineering conversion and display the sensor value. The problem here is that the code implemented by the concrete classes is the same no matter what Abstract
class it extends. CAnalogTempView
, CDigitalTempView
and CCustomTempView
all have the same implementation but extend different classes.
This seems awkward. The code is repeated and the number of source files increases by a factor of 3. Am I missing something simple here? Is there a pattern for a problem like this? Can I extends
the sensor view classes at run time? The actual code is more complicated. I have over simplified the problem statement for clarity.
EDIT: There are several sensor views which implement the Abstract
view classes. The calculate()
method for each sensor is different. I have just listed 3 concrete classes for simplicity. In the same vein, you would have CAnalogVoltageView
, CDigitalVoltageView
, CCustomVoltageView
and CAnalogCurrentView
, CDigitalCurrentView
, CCustomCurrentView
and so on
public abstract class CView
{
public abstract void draw();
public abstract void calculate();
}
public abstract class CAnalogView extends CView
{
public void draw()
{
// draw specific to analog view
}
}
public abstract class CDigitalView extends CView
{
public void draw()
{
// draw specific to digital view
}
}
public abstract class CCustomView extends CView
{
public void draw()
{
// draw specific to custom view
}
}
// concrete implementations
public class CAnalogTempView extends CAnalogView
{
public void calculate()
{
// read and calculate sensor value here
}
}
public class CDigitalTempView extends CDigitalView
{
public void calculate()
{
// calculate here. same as CAnalogTempView::calculate()
}
}
public class CCustomTempView extends CCustomView
{
public void calculate()
{
// calculate here. same as CAnalogTempView::calculate()
}
}
Strategy design pattern will help you. Well One thing that you should kept in mind.
Use as less
extends
keyword as possible, better to use Interfaces or composition.
Solution:
Encapsulate the calculate()
because calculate()
may change in future and it has different implementations.
Process:
1) Make an interface CalcInterface
that has calculate()
.
2) Implement CalcInterface
by 3 different classes say CAnalogTempCalc
, CDigitalTempCalc
and CCustomTempCalc
. Then implement calculate()
in each class.
3) Now its time for composition
. Say you have Sensor
class (main class) ... then make the object of type CalcInterface
. PS: it will has display()
that is common for all.
4) And now make 3 different classes that extends Sensor
say AnalogSensor
, TempSensor
and CustomSensor
...
5) Now at runtime you will make any of type's ( CAnalogTempCalc
, CDigitalTempCalc
and CCustomTempCalc
) object.
EDIT :
Following is the Class Diagram, I am not good with art ... but this diagram will give you some idea about classes and interfaces and how to use them efficiently.
Now you will be able to implement as many CustomCalcuations as you want by just implementing the CalcInterface
...
This is the POWER to accommodate change without changing current implementation you have by following Strategy design pattern.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments