Reputation: 172
I have an interface and its 2 implementations say :
public interface ObjectProcessor {
public void process(List<String> objectNames);
}
public CarImpl implements ObjectProcessor {
@override
public void process(List<String> carNames){
//car logic
} }
public VanImpl implements ObjectProcessor {
@override
public void process(List<String> vanNames){
//van logic
}
}
Now the caller who uses this interface looks like :
public void caller(VehicleType vehicleType, List<String> vehicleNames ) {
ObjectProcessor processor = null ;
if (VehicleType == VehicleType.CAR) {
processor = new CarImpl();
processor.process(vehicleNames);
}
}
VehicleType being an ENUM
This works fine. But is there anyway I can call an interface dynamically without
adding if statements. In the future if I am supporting another vehicle , I need to add an if statement along with a new implementation for the interface . How can I avoid this?
Upvotes: 12
Views: 10478
Reputation:
Overwrite abstract factory method in enum like this.
public enum VehicleType {
Car {
@Override
public ObjectProcessor createImpl() {
return new CarImpl();
}
},
Van {
@Override
public ObjectProcessor createImpl() {
return new VanImpl();
}
};
public abstract ObjectProcessor createImpl();
}
public void caller(VehicleType vehicleType, List<String> vehicleNames ) {
ObjectProcessor processor = vehicleType.createImpl();
processor.process(vehicleNames);
}
VechicleType combines enumeration with factory.
Or you can wirte all logics in enum like this.
public enum VehicleType {
Car {
@Override
public ObjectProcessor createImpl() {
return new ObjectProcessor() {
@Override
public void process(List<String> objectNames) {
// car logic
}
};
}
},
Van {
@Override
public ObjectProcessor createImpl() {
return new ObjectProcessor() {
@Override
public void process(List<String> objectNames) {
// van logic
}
};
}
};
public abstract ObjectProcessor createImpl();
}
In this case you don't need implementation classes (CarImpl, VanImpl, ...) any more.
Upvotes: 8
Reputation: 1
What you're basically implementing is a Factory pattern like proposed in the other answers. But in the end you will have to write an 'if' or 'switch' statement to select to correct implementation (or strategy) for your enum value. But like you mentioned yourself you'd have to extend this selection pattern whenever you add or remove an enum value. You can circumvent this by using a map like so:
public class ProcessorSelector {
private final Map<VehicleType, ObjectProcessor> processors;
public ProcessorSelector(Map<VehicleType, ObjectProcessor> processors) {
this.processors = processors;
}
public void process(VehicleType type, List<String> input) {
processors.get(type).process(input);
}
}
You can than configure your ProcessorSelector by passing a map with all the processor implementations mapped to the correct enum value (notice I used guava's ImmutableMap to conveniently construct the hashmap:
new ProcessorSelector(ImmutableMap.of(
VehicleType.CAR, new CarImpl(),
VehicleType.VAN, new VanImpl());
You'll never have to change your ProcessorSelector again, only the construction/configuration of the class. In fact you could say we just implemented the strategy pattern here. These selector classes are very common and if you feel you are implementing them quite often you could even use a more generic implementation, I recently described this in a blogpost: https://hansnuttin.wordpress.com/2015/12/03/functionselector/
Upvotes: 0
Reputation: 343
Use Factory pattern. Here are some benefit from using it: http://javarevisited.blogspot.com/2011/12/factory-design-pattern-java-example.html#ixzz3ueUdV947
1) Factory method design pattern decouples the calling class from the target class, which result in less coupled and highly cohesive code?
2) Factory pattern in Java enables the subclasses to provide extended version of an object, because creating an object inside factory is more flexible than creating an object directly in the client. Since client is working on interface level any time you can enhance the implementation and return from Factory.
3) Another benefit of using Factory design pattern in Java is that it encourages consistency in Code since every time object is created using Factory rather than using different constructor at different client side.
4) Code written using Factory design pattern in Java is also easy to debug and troubleshoot because you have a centralized method for object creation and every client is getting object from same place
Upvotes: 0