In order to do its work, a DataProcessor needs Data and otherData.
One instance of Data will be shared over a set of DataProcessor, but each DataProcessor has its own otherData.
For sharing Data instances, fields of Data could not be defined inside DataProcessor, thus, there are two hierarchies: Data and DataProcessor.
Each subClass of DataProcessor relates a subClass of Data.
And I have tried three design to fit the requirement, which way is the best? why?
Is my design bad? Why?
Is there any other solution?
Is there any existing design pattern to solve this kind of problem?
It is said that this is a "parallel inheritance hierarchy". Should I avoid this? How? Or is it a good design for my requirement, and do I not need to avoid?
Data hierarchies
abstract class Data {
int field1;
}
abstract class AData extends Data {
int field2;
}
class AAData extends AData {
int field3;
}
class BData extends Data {
int field4;
}
DataProcessor hierarchies way 1, each super class instance keeps a private reference to Data
abstract class DataProcessor {
private Data data;
protected Object otherData;
DataProcessor(Data data){
this.data = data;
}
void doSomethingUsingDataAndOtherData(){}
}
abstract class ADataProcessor extends DataProcessor {
private AData data;
ADataProcessor(AData data) {
super(data);
this.data = data;
}
void doSomethingUsingADataAndOtherData(){}
}
class AADataProcessor extends ADataProcessor {
private AAData data;
AADataProcessor(AAData data) {
super(data);
this.data = data;
}
void doSomethingUsingAADataAndOtherData(){}
}
class BDataProcessor extends DataProcessor {
private BData data;
BDataProcessor(BData data) {
super(data);
this.data = data;
}
void doSomethingUsingBDataAndOtherData(){}
}
DataProcessor hierarchies way 2, only top superclass instance keeps a protected reference to Data, when subclass needs to use the data, it has to cast the data to its expected Data subclass. And I don't want to define DataProcessor as DataProcessor, because once introducing generic types, I have to use generic types everywhere, and sometimes using generic types is not so simple (i.e. we can not create a generic array in java).
abstract class DataProcessor {
protected Data data;
protected Object otherData;
DataProcessor(Data data) {
this.data = data;
}
void doSomethingUsingDataAndOtherData(){}
}
abstract class ADataProcessor extends DataProcessor {
ADataProcessor(AData data) {
super(data);
}
void doSomethingUsingADataAndOtherData(){}
}
class AADataProcessor extends ADataProcessor {
AADataProcessor(AAData data) {
super(data);
}
void doSomethingUsingAADataAndOtherData(){}
}
class BDataProcessor extends DataProcessor {
BDataProcessor(BData data) {
super(data);
}
void doSomethingUsingBDataAndOtherData(){}
}
DataProcessor hierarchies way3, only bottom sub class instance keep a priavte reference to Data, super class use a abstract method getData() to retrieve the Data
abstract class DataProcessor {
protected Object otherData;
protected abstract Data getData();
void doSomethingUsingDataAndOtherData(){}
}
abstract class ADataProcessor extends DataProcessor {
protected abstract AData getData();
void doSomethingUsingADataAndOtherData(){}
}
class AADataProcessor extends ADataProcessor {
private AAData data;
protected AAData getData() {
return data;
}
AADataProcessor(AAData data) {
this.data = data;
}
void doSomethingUsingAADataAndOtherData(){}
}
class BDataProcessor extends DataProcessor {
private BData data;
protected BData getData() {
return data;
}
BDataProcessor(BData data) {
this.data = data;
}
void doSomethingUsingBDataAndOtherData(){}
}