Как я могу кучу ифов преобразовать в ООП
У меня есть бот который анализирует текст, который ему прислали. И в итоге я написал такую кашу из if
if (message.Message.Type != MessageType.Text)
{
LogAndDeleteUser(in message);
string ret = Random_Say();
gBot.SendTextMessageAsync(message.Message.Chat.Id, ret + ". Введи текстовый запрос");
i = 0;
}
else if (message.Message.Text.ToLower().Equals("/start"))
{
LogAndDeleteUser(in message);
Keyboard_help(ref message);
}
else if (message.Message.Text.ToLower().Trim().Equals("/List") || message.Message.Text.Contains("?"))
{
LogAndDeleteUser(in message);
new ListGroups().Cours(ref keyboard, ref message);
}
else if ((message.Message.Text.ToLower().Trim().Equals("/group") || message.Message.Text.Contains("?")) && i == 0)
{
LogAndDeleteUser(in message);
Rassilka.Add(message.Message.Chat.Id, true);
}
else if (message.Message.Text.ToLower().Trim().Equals("/me") || message.Message.Text.Contains("?"))
{
LogAndDeleteUser(in message);
Me(message);
Console.WriteLine(message.Message.Chat.Type);
}
Как мне это все превратить в пправильное ООП? Я думал сделать интерфейс, и наследование от него, но мне кажется это будет не правильно + я хочу гибкости, а как тут сделать гибкость, если привязка к тексту идет?
Ответы (1 шт):
ООП - это объекты, а значит первое, что нужно сделать, это разбить код на отдельные составляющие. Я не буду переписывать именно ваш код, покажу лишь небольшой пример:
Сделаем простой класс одной команды, допустим, так:
public class Command { public Action Action { get; init; } private string[] triggers { get; init; } public Command(Action action, params string[] triggers) => (Action, this.triggers) = (action, triggers); public bool HasTrigger(string trigger) => triggers.Contains(trigger); }Action- это то, что будет выполняться.triggers- так, как "триггеров", которые могут вызвать команду у нас может быть несколько, это массив.HasTrigger- проверяем, есть ли указанный триггер в команде или нет.
Далее давайте сделаем простой класс
Commands, он будет отвечать за хранение команд и их выдачу/вызов:public class Commands { private List<Command> commands = new(); public void Register(Command command) => commands.Add(command); public void Invoke(string trigger) { var command = commands.FirstOrDefault(x => x.HasTrigger(trigger)); if (command is not null) { command.Action.Invoke(); } else { NotFound(trigger); } // логгирование? } private void NotFound(string trigger) => Console.WriteLine($"Команда {trigger} не распознана!"); }Тут как видите тоже все весьма просто:
commands- некая коллекция, в которую мы будем добавлять команды (регистрировать их).Register- простой метод, который добавитCommandв коллекцию.Invoke- метод вызова нужной команды.NotFound- пример простого вывода сообщения о том, что команда не найдена.
Можете спросить "а зачем тут отдельные методы, почему мы не можем сделать коллекцию команд публичной и добавлять сразу в нее?", ответ очень прост - контроль. Когда у нас есть отдельный метод, мы может сделать, к примеру проверку нужную нам, или можем добавить логгирование, да много чего еще.
Все основное у нас готово, давайте соберем тестовый макет:
public class Time { public void SendTime() { Console.WriteLine(DateTime.Now); } } class Program { private Commands commands = new(); public Program() { commands.Register(new(SendMe, "/me", "/мне")); commands.Register(new(new Time().SendTime, "/time", "/время")); } static void Main(string[] args) => new Program().Start(); public void Start() { while (true) { Console.Write("Команда: "); commands.Invoke(Console.ReadLine()); Console.ReadKey(); Console.Clear(); } } public void SendMe() { Console.WriteLine("Отправили Me"); } }
Вот вам и простой пример реализации команд, где вся логика сводится к вызову методов .Register() и .Invoke(). Заметьте, в примере я специально сделал класс Time, который наглядно показывает то, что команды могут быть где угодно в нашем проекте, а также то, что вся логика может быть (да и должна) разбита на отдельные методы/классы. Вам же тут остается переписать этот пример на тип Message, чтобы можно было в случае чего проверить тип, ну это я думаю не составит для вас труда.
Это конечно базовая демонстрация, тут нет много чего, например, передача параметров. Также стоит позаботиться о неких ограничениях, чтобы нельзя было любой метод регистрировать в качестве команды, сделать, например интерфейс, который будет четко помечать те классы, которые реализуют команду и на его основе уже дальше следовать.
Если проект весьма сложный, то регистрацию команд можно автоматизировать. Для этого многие используют атрибуты, по которым потом определяют является ли класс "командным" или нет, но это уже совсем другая история)
