I have different class types, and depending on some conditions, I want to delegate to the appropriate service
that can handle those class types.
Example: I have several classes as follows.
class Student;
class Prof;
...
For each class there is a service, implementing:
interface IPersonService {
void run();
}
And I have a mode
that is found by some conditions:
enum PersonType {
STUDENT, PROF;
}
When I delegate:
@Autowired
private StudentService studentService;
@Autowired
private ProfService profService;
//@param mode assume known
public void delegate(PersonType mode) {
//assume there are several of those switch statements in my business code
switch (mode) {
case STUDENT: studentService.run(); break;
case PROF: profService.run(); break;
default: break;
}
}
Problem: When introducing additional classes, I have to both modify the PersonType
and add an additional enum (which is no problem), but I also have to extend any switch
statement and add calls to additional delegation services. Also I have to explicit autowire those services to the switch delegator.
Question: how could I optimize this code, to just implementing new Services for any additional class, and not having to touch any of the switch statements?
Add a method to IPersonService
so that the implementation of the method can tell the program what type of persons it handles:
interface IPersonService {
PersonType supportedPersonType();
void run();
}
In the service that does the delegation, inject a List<IPersonService>
, which Spring will fill with all the implementations of IPersonService
that it can find. Then implement the delegate
method to look through the list to find the first IPersonService
that can handle the specific type.
@Autowired
private List<IPersonService> personServices;
public void delegate(PersonType mode) {
for (IPersonService personService : personServices) {
if (personService.supportedPersonType().equals(mode)) {
personService.run();
break;
}
}
}
This way, you can add new implementations of IPersonService
without having to change the service that does the delegation.
To avoid having to go through the loop each time delegate
is called, you could build a Map
beforehand so that the right IPersonService
can be looked up quickly:
class DelegatingService {
@Autowired
private List<IPersonService> personServices;
private Map<PersonType, IPersonService> personServiceMap;
@PostConstruct
public void init() {
personServiceMap = new HashMap<>();
for (IPersonService personService : personServices) {
personServiceMap.put(personService.supportedPersonType(), personService);
}
}
public void delegate(PersonType mode) {
personServiceMap.get(mode).run();
}
}
(Error handling omitted for simplicity).
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