I use spring boot. Instead of using many if condition based on state of a object to do a process, I search to use a strategy pattern
if (StatutDepositEnum.SAVED.getCode().equals(deposit.status)){
}
else if(){
}
public interface NoticeTemplateService(){
void apply();
}
@Service
public class ConfirmationNoticeTemplateService implements NoticeTemplateService{
public void apply(){
}
}
I know I could put the status name to every class who implement NoticeTemplateService, but because the status has nothing to do with class name, i would like to avoid that
So I search to use deposit status like the key of the map.
@RequiredArgsConstructor
@Service
public class NoticeService{
public final Map<String, NoticeTemplateService> mapNoticeTemplateService;
@PostConstruct
public void init(){
mapNoticeTemplateService = new HashMap<>();
}
public void createNotice(){
NoticeTemplateService noticeTemplateService = mapNoticeTemplateService.get(deposit.status);
}
}
How to add instance to the map? All class use Service annotation;
I use spring boot. Instead of using many if condition based on state of a object to do a process, I search to use a strategy pattern
if (StatutDepositEnum.SAVED.getCode().equals(deposit.status)){
}
else if(){
}
public interface NoticeTemplateService(){
void apply();
}
@Service
public class ConfirmationNoticeTemplateService implements NoticeTemplateService{
public void apply(){
}
}
I know I could put the status name to every class who implement NoticeTemplateService, but because the status has nothing to do with class name, i would like to avoid that
So I search to use deposit status like the key of the map.
@RequiredArgsConstructor
@Service
public class NoticeService{
public final Map<String, NoticeTemplateService> mapNoticeTemplateService;
@PostConstruct
public void init(){
mapNoticeTemplateService = new HashMap<>();
}
public void createNotice(){
NoticeTemplateService noticeTemplateService = mapNoticeTemplateService.get(deposit.status);
}
}
How to add instance to the map? All class use Service annotation;
Share Improve this question asked 5 hours ago robert trudelrobert trudel 5,76918 gold badges87 silver badges142 bronze badges 3- what you want to use as a key of the map? – Geba Commented 5 hours ago
- like i wrote... "So I search to use deposit status like the key of the map." – robert trudel Commented 5 hours ago
- sorry, my bad. Missed it – Geba Commented 5 hours ago
2 Answers
Reset to default 0Want you want is a map that holds a reference between Status and the the concrete NoticeServiceImpl that performs the right operation.
@Configuration
public class BeanHolder {
@Bean
public Map<StatutDepositEnum, NoticeTemplateService> servicesMap(ConfirmationNoticeTemplateService serviceA, RejectionNoticeTemplateService serviceB, ...) {
return Map.of(
StatutDepositEnum.SAVED, serviceA,
StatutDepositEnum.REJECTED, serviceB,
....
);
}
}
You can inject this Bean wherever you need it.
@RequiredArgsConstructor
@Service
public class NoticeService{
private final Map<StatutDepositEnum, NoticeTemplateService> mapNoticeTemplateService;
public void createNotice(){
NoticeTemplateService noticeTemplateService = mapNoticeTemplateService.get(deposit.status);
...
noticeTemplateService.apply();
}
}
If you want to use as a key your custom type (e.g. StatusDepositEnum
),
then I suggest following
enum StatusDepositEnum {
REJECTED,
COMPLETED;
}
interface NoticeTemplateService{
void apply();
StatusDepositEnum getStatus();
}
@Service
class ConfirmationNoticeTemplateService implements NoticeTemplateService {
@Override
public void apply() {}
@Override
public StatusDepositEnum getStatus() {
return StatusDepositEnum.COMPLETED;
}
}
@Service
class RejectNoticeTemplateService implements NoticeTemplateService {
@Override
public void apply() {}
@Override
public StatusDepositEnum getStatus() {
return StatusDepositEnum.REJECTED;
}
}
@Service
class NoticeService{
@Autowired
private List<NoticeTemplateService> templates;
private Map<StatusDepositEnum, NoticeTemplateService> statusToTemplate;
@PostConstruct
public void init(){
statusToTemplate = templates.stream()
.collect(Collectors.toMap(
NoticeTemplateService::getStatus,
service -> service
));
}
public void createNotice(){}
}
If you are ok to set bean names, I would suggest to take a look to the approach described in this answer https://stackoverflow/a/63661216/7613649.
For you it will look like this:
@Service("CONFIRM")
class ConfirmationNoticeTemplateService implements NoticeTemplateService {
@Override
public void apply() {}
}
@Service("REJECT")
class RejectNoticeTemplateService implements NoticeTemplateService {
@Override
public void apply() {}
}
@Service
class NoticeService{
@Autowired
private Map<String, NoticeTemplateService> statusToTemplate;
public void createNotice(){}
}