Мой благородный квест - избавиться от синглетонов и статических классов.
Фон:
У меня есть следующие структуры:
- Cmd
Часто создаваемый объект, он содержит имя команды (строка) и функтор статического метода любого класса в качестве указателя.
Обычно создается в основных классах, таких как Input, Console, Renderи т. д. и относится к методам внутри класса, в котором он создается, предоставляя вербальный интерфейс времени выполнения для этих методов.
Cmds также интерпретирует параметры в виде массива строк, где первый аргумент - это имя Cmd,и все последовательные строки являются прямыми аргументами для вызываемого статического метода.Количество аргументов и массив аргументов хранятся в Commander и изменяются перед каждым вызовом Cmd. - Commander
Commander используется для интерпретации строковых команд (которые могут поступать напрямую или через консоль), и он выполняет Cmdкоторый был сохранен в буфере как строка (вызывая его функтор).
Проблема:
Проблема в том, что я пытаюсь избавиться от всех статических классов(который я теперь превратил в синглтоны для тестирования), и я делаю систему полностью модульной и слабо связанной.Это, в свою очередь, препятствует тому, чтобы у меня были статические вызовы, на которые мог бы указывать Cmds.
Первым инстинктом было изменение функтора из typedef в класс шаблона, который будет хранить объект и метод, но это выглядит очень грязно исложный, и мне лично неудобно переходить от:
Cmd::create("toggleconsole", Console::toggle);
к:
Cmd::create("toggleconsole", new FunctorObject<Console>(&Console::get(), &Console::toggle));
Окончательное создание Cmd выглядит очень неясным и вводящим в заблуждение относительно того, кто отвечает за освобождение Functor.
Я также нахожусь в процессе переноса создания Cmd из вызова статического метода в класс Commander, поэтому он будет выглядеть как commander.createCmd ("имя_команды", ...); вместо Cmd :: create ("имя_команды", ...); Это потому, что Commander больше не будет статичным (или синглтоном), поэтому все команды, которые он обрабатывает, должны принадлежать ему.
Я, однако, в полной растерянности относительно того, каковы мои варианты / альтернативы, чтобы зарегистрировать Cmds и поддерживать слабую связь, позволяя командным командам выдавать строковые командыmmander.
Я рассмотрел вопрос о том, чтобы сделать каждый из основных классов производным от класса CmdListener, который регистрировал бы объект с помощью Commander при создании, а затем во время выполнения передавал команду всем зарегистрированным объектам, которые перезаписали "onCmd".(const Cmd & command) ".
Это также оставляет некоторые вопросы без ответа: как Cmd будет передавать, какой метод класса должен быть вызван?Хранение указателей не имело бы смысла и было бы подвержено высокому уровню неясности (как показано выше).Кроме того, я не хочу переинтерпретировать строки в методе onCmd для каждого класса, который может обрабатывать этот cmd.
Это много информации, но есть ли у кого-нибудь идеи о том, как иметь дело сэта проблема?
Кроме того, все мои классы должны знать объекты Commander и Console, которые больше не являются одноэлементными / статическими.До сих пор я поместил их в объект Context и передаю его как маленькую капсулу.Любые идеи о том, как решить эти остаточные проблемы после синглтона?
Этот проект - моя личная работа, и я планирую использовать его в своем резюме - следовательно, я не хочу, чтобы мои потенциальные работодатели видели какие-либо одиночные игры(и при этом я не хочу объяснять себе, почему, поскольку я могу доказать себе, что они действительно не нужны).
Спасибо за тонну!
edit: типографика.