I am working on a component which is supposed to:
-
receive data (collection of items) from some external calculation component. I expect about 100-1K of items on input on each request.
-
validate data, calculate some attributes if missing
-
persist data
There are about ten types of items. I use inheritance to model items. I have a base item class with common attributes and calculations and subclasses implementing type specific problems. Similar to following example:
public abstract class BaseItem {
String name;
boolean valid = true;
public void postCalucate() {
//common calculation
valid = valid && (name != null);
}
}
public class ItemA extends BaseItem {
BigDecimal value;
@Override
public void postCalucate() {
//some A specific calculations
super.postCalucate();
}
}
public class ItemA1 extends ItemA {
BigDecimal extraValue;
@Override
public void postCalucate() {
//some A1 subtype specific calculations
valid = isA1ItemValid();
super.postCalucate();
}
}
public class ItemB extends BaseItem {
Integer size;
@Override
public void postCalucate() {
//some B specific calculations
super.postCalucate();
}
}
Is there any better way/pattern to do my task? Any advices?
The pattern you are trying to use is fairly sound. In general, I would probably suggest the use of an interface instead of a
BaseItemclass, since it might not contain that much common functionality.In general, most people seem to recommend defining interfaces for your classes to implement. If absolutely you want to share common code in an AbstractClass, I would recommend that class implementing the interface, since this pattern would lend itself to greater extensibility and flexibility in the future.
As such, you would first begin by defining what an Item is for you. For me, it seems that an Item is three things in your use case: one, it must define the
postCalculate()method that will be called on all Items. Second, it must provide anisValid()method. And third, it should also provide agetName()method.Then you would begin implementing your Abstract class. Do this only if it really is necessary to share a codebase between all your items.
If BaseItem.postCalculate() is something that will need to be done for all items, this is a good way to do it. If you’re not entirely sure, it might be a good idea instead to define a method somewhere in a
HelperorToolclass that performs this common calculation for items, and is called by thepostCalculate()methods:This, many would argue, gives you an easier time as your requirements on
BaseItemmay change over time.Regardless of which route you go there, now you’ll just have to define your actual items: