psvaibhav psvaibhav - 9 days ago 8
Java Question

JAVA - extends vs interface - Strategy design pattern

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

Answer

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.

enter image description here

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.

Comments