I have legacy code, similar to this
private Resource getResource(String type){
Resource resource = null;
if("A".equals(type)){
resource = Utils.getResourceA(); //static func
}else if("B".equals(type)){
resource = Utils.getResourceB(); //static func
}else if("C".equals(type)){
resource = Utils.getResourceC(); //static func
}else if // etc..
}
As you can see it's something that will be hard to maintain for new types...
What is the best practice to solve that?
I was thinking of creating Class for each resource function that will implement same interface.
Then create a Map<String,IResource> key is the type and IResource will be the instance of class.
But there are problems with this solution.
A note: I am not using any frameworks, pure java.
Thanks
The usual solution is indeed the one you describe. Example using Java 8 (but that could be written, in a more verbose way, in Java7):
private Map<String, Supplier<Resource>> resourceSuppliers;
public TheClass() {
resourceSuppliers = new HashMap<>();
resourceSuppliers.put("A", Utils::getResourceA);
resourceSuppliers.put("B", Utils::getResourceB);
resourceSuppliers.put("C", Utils::getResourceC);
...
}
private Resource getResource(String type){
return resourceSuppliers.get(type).get();
}
The map could also be static final and shared by all instance of TheClass, if the type/resource mapping is the same for all instances:
private static final Map<String, Supplier<Resource>> RESOURCE_SUPPLIERS = createResourceSuppliers();
private static Map<String, Supplier<Resource>> createResourceSuppliers() {
// same code as in constructor above
}
In older Java versions, you would have to define the Supplier interface, and to define the suppliers by creating them in a more explicit way, for example, using an anonymous inner class:
resourceSuppliers.put("A", new Supplier<Resource>() {
@Override
public Resource get() {
return Utils.getResourceA();
}
});
The best way it to turn type into an enum. This will prevent arbitrary types and requires implementing the getResource() method for any new type.
public enum ResourceType {
A {
@Override
public Resource getResource() {
return Utils.getResourceA();
}
},
B {
@Override
public Resource getResource() {
return Utils.getResourceB();
}
},
C {
@Override
public Resource getResource() {
return Utils.getResourceC();
}
};
public abstract Resource getResource();
}
Update
Converting String to enum is easy (built-in):
ResourceType type = ResourceType.valueOf("A");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With