Признаюсь, я совершил грех, злоупотребляя и даже злоупотребляя наследством. Первый (текстовый) игровой проект, который я сделал, когда проходил курс обучения по ООП, дошел до «Запертой двери» и «Открытой двери» от «Дверь» и «Комната с одной дверью», «Комната с двумя дверями» и так далее из "Комнаты".
В (графической) игре, над которой я недавно работал, я подумал, что усвоил урок и наложил ограничения на использование наследования. Однако я заметил, что проблемы скоро начинают появляться. Мой корневой класс начал раздуваться все больше и больше, и мои классы листьев были полны дублирующих кодов.
Я думал, что все еще делаю что-то не так, и, просмотрев его в Интернете, я обнаружил, что я не единственный, кто столкнулся с этой проблемой. Именно так я и обнаружил системы Entity после тщательного исследования (читай: googlefu)
Когда я начал читать его, я смог увидеть, насколько ясно он смог решить проблемы, которые у меня были с традиционной иерархией ООП с компонентами. Это было в первых чтениях однако. Когда я наткнулся на более… «радикальные» подходы ES, такие как на T-machine .
Я начал не соглашаться с методами, которые они использовали. Чистая система компонентов казалась либо излишней, либо, скорее, неинтуитивной, что, вероятно, является сильной стороной ООП. Автор доходит до того, что говорит, что система ES является противоположностью ООП, и, хотя она может использоваться в ООП, она действительно не должна. Я не говорю, что это неправильно, но я просто не чувствовал себя таким решением, которое хотел бы реализовать.
Поэтому для меня и для решения проблем, которые у меня были в начале поста, не противореча моей интуиции, все равно нужно использовать иерархию, однако это будет не монолитная иерархия, подобная той, которую я использовал раньше, а скорее полилитичный (я не мог найти слово, противоположное монолитному), который состоит из нескольких меньших деревьев.
Следующий пример показывает, что я имею в виду (это вдохновлено примером, который я нашел в Game Engine Architecture, глава 14).
У меня было бы небольшое дерево для транспортных средств. Корневой класс транспортного средства будет иметь компонент рендеринга, компонент столкновения, компонент положения и т. Д.
Тогда танк, подкласс транспортного средства, унаследует эти компоненты от него и получит свой собственный компонент «пушка».
То же самое касается персонажей. Персонаж будет иметь свои собственные компоненты, тогда Класс Игрока унаследует его и получит контроллер ввода, в то время как другие классы врага наследуют от класса Персонажа и получат контроллер AI.
Я действительно не вижу никаких проблем с этим дизайном. Несмотря на то, что система Entity Controller не используется, проблема с эффектом всплытия и большим корневым классом решается с помощью иерархии из нескольких деревьев, а проблема тяжелых дублирующих листы кода исчезла, поскольку листы не есть код для начала, только компоненты. Если необходимо внести изменения на конечный уровень, это так же просто, как изменить один компонент, вместо того, чтобы копировать код везде.
Конечно, будучи таким же неопытным, как и я, я не увидел никаких проблем, когда впервые начал использовать единую иерархию, модель с наследованием, поэтому, если возникнут проблемы с моделью, которую я сейчас собираюсь реализовать, я бы не стал быть в состоянии увидеть это.
Ваши мнения?
PS: я использую Java, поэтому использование множественного наследования вместо обычных компонентов невозможно.
PPS: межкомпонентная связь будет осуществляться путем связывания зависимых компонентов друг с другом. Это приведет к соединению, но я думаю, что это хороший компромисс.