Не знаю как избавиться от большого количества параметров в конструкторе
Всем привет. Делаю свой первый проект и решил воспользоваться паттерном Command. В этом паттерне есть специальный класс CommandContainer. И так как каждая группа команд работает с несколькими сервисами, то конструктор будет иметь в будущем много параметров. Пример конструктора моего конструктора:
public class CommandContainer {
private final Map<String, Command> commandMap = new HashMap<>();
private final Command unknownCommand;
public CommandContainer(SendBotMessageService sendBotMessageService, WorkerService workerService) {
commandMap.put(CommandName.START.getCommandName(), new StartCommand(sendBotMessageService));
commandMap.put(CommandName.HELP.getCommandName(), new HelpCommand(sendBotMessageService));
commandMap.put(CommandName.CREATE_WORKER.getCommandName(),
new CreateWorkerCommand(sendBotMessageService, workerService));
unknownCommand = new UnknownCommand(sendBotMessageService);
}
public Command retrieveCommand(String commandIdentifier) {
return commandMap.getOrDefault(commandIdentifier, unknownCommand);
}
}
Ну и помимо SendBotMessageService sendBotMessageService, WorkerService workerService нужно будет добавлять и другие сервисы, которые работают с командами.
Подскажите как это можно упростить?
Ответы (1 шт):
Учитывая, что в тегах вопроса присутствует spring, можно воспользоваться группировкой бинов в коллекции .
Судя по коду - все команды являются наследниками класса Command (либо - реализуют интерфейс Command, в данном случае это не играет роли).
Тогда, код можно упростить до:
@Component
public class CommandContainer {
private final Map<String, Command> commandMap;
private final Command unknownCommand;
public CommandContainer(List<Command> commands, UnknownCommand unknownCommand) {
// технически - получать отдельно UnknownCommand не нужно - её вполне можно вычленить из общего списка commands
commandMap = commands.stream()
.filter(command->!Objects.equals(command.getCommandName(), unknownCommand.getCommandName())
.collect(Collectors.toUnmodifiableMap(Command::getCommandName, command->command, (o1, o2)->o1);
this.unknownCommand = unknownCommand;
}
public Command retrieveCommand(String commandIdentifier) {
return commandMap.getOrDefault(commandIdentifier, unknownCommand);
}
}
Каждый бин, наследующийся (или реализующий) Command, в своем конструкторе пускай получает тот набор бинов, который ему нужен. Это будут его личные потребности, о которых контейнеру знать совершенно не интересно. Главное, чтобы все параметры были бинами:
@Component
public class UnknownCommand extends Command {
private final SendBotMessageService sendBotMessageService;
public UnknownCommand(SendBotMessageService sendBotMessageService){
this.sendBotMessageService = sendBotMessageService;
}
public String getCommandName(){
return "Unknown";
}
}
Всё остальное будет проблемами Spring: определить параметры конструктора каждой команды (и контейнера команд), построить граф зависимостей, и, наконец, в правильном порядке вызвать конструкторы с подстановкой требуемых объектов.