Насколько разумно при композиции позволять компоненту управлять родителем?
Насколько адекватно будет внутри объекта1 создавать атрибут, хранящий объект2, который будет содержать ссылку на объект1 и управлять им?
Например, у нас есть класс автомобиля `Car` (наследуется от `RigidBody` игрового движка). Мы захотели чтобы одни автомобили управлялись искусственным интеллектом, другие - игроком. Это не настолько значительная деталь, чтобы создавать двух наследников. Поэтому я решил использовать композицию (возможно, в подобных ситуациях можно использовать наследование, но допустим, что пришли к выводу что без композиции не обойтись - мой пример абстрактный)
В классе `Car` у меня появляется атрибут `driver` типа `Driver`, создаем `AiDriver` и `PlayerDriver`. Первый использует алгоритм для управления, второй - ввод игрока.
Так в чем суть: единственное решение, которое я пока нашел это то, что компоненты `Driver` имеют в себе ссылку на родителя - `driven_car` и в коде вызывают `driven_car.gas()` и `driven_car.brake()` и т. п., т. е. управляют своим родителем. Я слышал (и есть шанс, что ошибаюсь, почему и задаю этот вопрос) что ребенок не то что управлять родителем не может, но и знать не должен о нем вообще, а тут ситуация обратная. Не навредит ли такой подход архитектуре в будущем?
P. S.: указал в тегах Godot, так как делаю в нем, но пример, как я думаю, достаточно общий, чтобы решить его без знания движка. Возможно он предоставляет какие-то дополнительные возможности. Конкретно в моей реализации компоненты - ноды, при этом как родитель знает о компоненте, так и наоборот : (
С точки зрения ЯП/Рантайма, это приведет к кольцевой зависимости, а это порождает различные баги (например, освобождение памяти), поэтому так лучше не делать.
С точки зрения проектирования, Car не должен знать о Driver - это Driver должен знать о Car, т.к. он ей управляет. Здесь, по факту, водитель - это контроллер какого-то объекта.
А куда в таком случае помещать драйвера, к кому его привязать? Драйвер должен получать некоторые данные (например, массу) от Car. В моей реализации Car его и инициализирует, поэтому хранит у себя. Либо создать общий массив (что мне не нравится) куда Car'ы сами будут помещать драйвера. Либо фабрику, создающую эти машины и хранящую все драйверы у себя в таком же массиве. Тут же всплывает проблема с удалением машин, придется обходить массив драйверов.
На кольцевую зависимость движок не жалуется (судя по всему, пока не жалуется), а решения более адекватные в голову не приходят, из-за чего так и хочется пренебречь этим принципом проектирования.
r245_r, драйвер - это контроллер машины - ни к кому его привязывать не надо, максимум к основной сцене. Он, можно сказать, ни от кого не зависит, управляет всем.