如何按类类型委托服务?

mem*_*und 6 java design-patterns

我有不同的类类型,并且根据某些条件,我想委托适当的service,可以处理这些类类型.

示例:我有几个类如下.

class Student;
class Prof;
...
Run Code Online (Sandbox Code Playgroud)

每个班级都有一项服务,实施:

interface IPersonService {
    void run();
}
Run Code Online (Sandbox Code Playgroud)

我在mode某些条件下找到了一个:

enum PersonType {
    STUDENT, PROF;
}
Run Code Online (Sandbox Code Playgroud)

当我委托时:

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:在引入其他类时,我必须修改PersonType并添加一个额外的枚举(这没有问题),但我还必须扩展任何switch语句并添加对其他委托服务的调用.此外,我必须显式自动将这些服务自动装配到交换机委托人.

问题:如何优化此代码,为任何其他类实现新服务,而不必触及任何switch语句?

Jes*_*per 6

添加一个方法,IPersonService以便该方法的实现可以告诉程序它处理的人员类型:

interface IPersonService {
    PersonType supportedPersonType();
    void run();
}
Run Code Online (Sandbox Code Playgroud)

在执行委托的服务中,注入一个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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,您可以添加新的实现,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();
    }
}
Run Code Online (Sandbox Code Playgroud)

(为简单起见省略了错误处理).