Всем привет. Не могу понять. Как обработать команду? Допустим в string command у меня есть слово с командой. Допустим, что command = "скажи". У меня есть 100 классов, каждый из которых отвечает за нужную команду. Как вызвать код, который относится именно к этой команде т.е именно класс Say? Я думаю, что использовать switch или if else if неправильно. Что можно придумать в таком случае?
Для начала определимся с тем, какие структуры данных нам могут понадобится. Очвидно, у нас должны быть интерфейсы для команды и для оработчика команды.
// Команда и прямая реализация
public interface ICommand
{
string CommandName { get;}
}
public class Command : ICommand
{
public Command(string name)
{
CommandName = name;
}
public string CommandName { get; private set; }
}
// Обработчик команды
public interface ICommandProcessor
{
void ProcessCommand(ICommand command);
bool CanProcess(ICommand command);
}
Далее, нам нужны 2 простых обработчика. Вот они:
public class PrintCommandProc : ICommandProcessor
{
public bool CanProcess(ICommand command)
{
return command.CommandName == "print";
}
public void ProcessCommand(ICommand command)
{
if (!CanProcess(command)) throw new ArgumentException(nameof(command));
Console.WriteLine($"{command.CommandName} command processed");
}
}
public class ReadCommandProc : ICommandProcessor
{
public bool CanProcess(ICommand command)
{
return command.CommandName == "read";
}
public void ProcessCommand(ICommand command)
{
if (!CanProcess(command)) throw new ArgumentException(nameof(command));
Console.WriteLine($"{command.CommandName} command processed");
}
}
Что делать дальше: так как вы не уточнили, могут ли одну и ту же команду обрабатывать несколько обработчиков, я покажу 2 подхода, которые немного отличаются. Причем вы в любой момент сможете заменить один подход другом.
Итак, вариант 1, случай, когда несколько обработчиков МОГУТ обрабатывать одну и ту же команду. Для этого создадим композитный обработчик, который будет держать список всех доступых обработчиков:
public class CompositeCommandProcessor : ICommandProcessor
{
ICommandProcessor[] _commandProcs;
public CompositeCommandProcessor(params ICommandProcessor[] commandProcs)
{
_commandProcs = commandProcs;
}
public bool CanProcess(ICommand command)
{
return _commandProcs.Any(c=>c.CanProcess(command));
}
public void ProcessCommand(ICommand command)
{
if (!CanProcess(command)) throw new ArgumentException(nameof(command));
foreach (var cp in _commandProcs.Where(c=>c.CanProcess(command)))
cp.ProcessCommand(command);
}
}
Как видите, эту команду можно инициализировать любым набором обработчиков, а также каждая команда проходит через каждый обработчик. Таким образом, для одной и той же команды можно зарегистрировать несколько обработчиков.
Использование:
var commandProc = new CompositeCommandProcessor(new PrintCommandProc(), new ReadCommandProc());
var printCommand = new Command("print");
var readCommand = new Command("read");
if (commandProc.CanProcess(printCommand)) commandProc.ProcessCommand(printCommand);
if (commandProc.CanProcess(readCommand)) commandProc.ProcessCommand(readCommand);
Вариант 2. Если для 1 команды возможен только 1 обработчик. Все, что надо сделать - это написать другой вариант композитного обработчика.
public class CompositeCommandProcessorDictionary : ICommandProcessor
{
Dictionary<string, ICommandProcessor> _processors = new Dictionary<string, ICommandProcessor>();
public void Register(string commandName, ICommandProcessor processor)
{
_processors.Add(commandName, processor);
}
public bool CanProcess(ICommand command)
{
return _processors.ContainsKey(command.CommandName);
}
public void ProcessCommand(ICommand command)
{
if (!CanProcess(command)) throw new ArgumentException(nameof(command));
_processors[command.CommandName].ProcessCommand(command);
}
}
Этот вариант основан на словаре, потому не получится заркгистрировать 2 обработчика на команду. Как использовать:
var commandProcDict = new CompositeCommandProcessorDictionary();
commandProcDict.Register("print", new PrintCommandProc());
commandProcDict.Register("read", new ReadCommandProc());
var printCommand = new Command("print");
var readCommand = new Command("read");
if (commandProcDict.CanProcess(printCommand)) commandProcDict.ProcessCommand(printCommand);
if (commandProcDict.CanProcess(readCommand)) commandProcDict.ProcessCommand(readCommand);
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники