I got in to a design problem where I have different implementation for saving the data and processing other things for the different tools. I used a factory design for saving the data and same in getting the data from the database.
class SaveDataService {
public void saveData(Data data) {
}
public List<Tool> getTools() {
return List.of();
}
}
class FishToolSaveDataService extends SaveDataService {
@Override
public void saveData(Data data) {
}
@Override
public List<Tool> getTools() {
return List.of(Tool.FISH);
}
}
class DogSaveDataService extends SaveDataService {
@Override
public void saveData(Data data) {
}
@Override
public List<Tool> getTools() {
return List.of(Tool.DOG);
}
}
class Data {
JsonNode data;
int version;
}
enum Tool {
FISH,
DOG
}
So, My Factory mapper is based on the enum Tool
Now I have a version for each tool to maintain but the saving implementation changes for each version. How do I maintain this without using if else checks in the saveData(Data data) method implementation.
I tried simple if/else check for version the saveData method but it will prolonged to long if I have five different version and two different tools have same logic of saving for the different version. That is duplicating my code.
How can I design this version such that I can reuse my code?
I have 15 tools implementation in to total and I am starting with the version 2 of 3 tools in total but in future more versioning and more tools will come.
It appears that the problem statement is to be able to create classes that can hold the logic for different Tool types and version combinations. This is a complicated problem statement that can only be answered via an example.
Start by creating an interface to represent the logic for saving a particular version :
Define some concrete/generic logic for different versions.
Now you might have requirements to execute specific logic based on tool type which is not generic. For this, you can create more specialized subclasses such as the one below :
We now create a
VersionDataServiceFactorythat will hold a map. This map will contain the pre-createdVersionDataServiceobjects for different permutation/combinations. (See the example at the end which will make more sense later)Now let's put all this together :
Notice how the
alphaobject was reused for both Fish and Dog alpha versions. This solves your objective of reusing the code for different tool types without using if-else. Also notice that whensaveDataService.save(data);is called, it automatically fetches the correctVersionDataServiceimplementation for the given Tool type and version combination.Note : This is a slightly complicated design problem. The code has not been tested but is only indicative of the approach that can be followed. There are a lot more improvements that can be done such as using the
Decoratorpattern to avoid having to create too many subclasses for each version + tool combination or using theAbstractFactorypattern, or defining a class calledVersionDataKeyto represent the key for the factory map and much more; but these are aspects intentionally left out for the readers (including you) to discover as covering these aspects would make this answer too long.