我有不同的类类型,并且根据某些条件,我想委托给可以处理这些类类型的相应service
。
实施例: 我有几个课程如下。
class Student;
class Prof;
...
每个班级都有一项服务,实施:
interface IPersonService {
void run();
}
我在某些条件下找到了mode
:
enum PersonType {
STUDENT, PROF;
}
当我委托时:
@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;
}
}
问题:在引入其他类时,我必须修改PersonType
并添加一个额外的枚举(这没问题),但我还必须扩展任何{{1语句并添加对其他委托服务的调用。此外,我必须将这些服务显式自动装配到交换机委托人。
问题:我如何优化此代码,为任何其他类实现新服务,而不必触及任何switch语句?
答案 0 :(得分:5)
向IPersonService
添加一个方法,以便该方法的实现可以告诉程序它处理的人员类型:
interface IPersonService {
PersonType supportedPersonType();
void run();
}
在执行委派的服务中,注入一个List<IPersonService>
,Spring将填充它可以找到的IPersonService
的所有实现。然后实现delegate
方法查看列表,找到可以处理特定类型的第一个IPersonService
。
@Autowired
private List<IPersonService> personServices;
public void delegate(PersonType mode) {
for (IPersonService personService : personServices) {
if (personService.supportedPersonType().equals(mode)) {
personService.run();
break;
}
}
}
这样,您可以添加IPersonService
的新实现,而无需更改执行委派的服务。
为避免每次调用delegate
时都要经过循环,您可以事先构建Map
,以便快速查找正确的IPersonService
:
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();
}
}
(为简单起见省略了错误处理)。
答案 1 :(得分:1)
在我的应用程序中,我们通过将服务放入地图来解决类似的问题。考虑Map<PersonType,IPersonService> serviceMap
定义为bean并注入您的类。
然后委托方法简单做
public void delegate(PersonType mode) {
IPersonService service = serviceMap.get(mode);
if (service!=null){
service.run();
}else{
//do something if service is null
}
}
答案 2 :(得分:0)
您可以将服务bean名称(或类类型)存储在枚举中,并使用getBean按名称(或分别按类类型)从应用程序上下文中获取bean。
此外,所有服务都需要实现一个具有run方法的接口。
interface ModeService {
void run();
}
enum PersonType {
STUDENT("studentService"), PROF("profService");
private String serviceBean;
public PersonType(String serviceBean) {
this.serviceBean = serviceBean);
}
public String getServiceBean() {
return serviceBean;
}
}
在委托中,可以使用以下内容。 ((ModeService)applicationContext.getBean(mode.getServiceBean()).run()
这样只需要使用要使用的服务类型更新枚举,并且不需要更改委托方法。