Бог-объект или где хранить ссылки на подсистемы

У меня много подсистем моей игры. Они могут использовать друг друга. Раньше я инициализировал и сохранял ссылки на подсистемы в статическом объекте Game вместо создания синглтона. Теперь я вижу, что Game имеет слишком много ссылок на другие классы и выглядит сбивающим с толку:

public static PlayerSettings PlayerSettings { get { return _playerSettings; } }

public static CommunityClient Community { get; private set; }
public static DatabaseConnectionWrapper Database { get; set; }
public static LoginConnectionWrapper LoginProtocolConnection { get; set; }
public static WorldEmulatorConnection WorldEmulatorConnection { get; set; }
public static WorldPlayerConnection WorldPlayerConnection { get; set; }
public static WorldConnection WorldConnection { get { return IsEmulatorMode ? (WorldConnection)WorldEmulatorConnection : WorldPlayerConnection; } }

public static MusicManager MusicManager { get; private set; }
public static SkyboxManager SkyboxManager { get; private set; }

public static VKInfo VK { get; private set; }

Что я могу с этим поделать? Мне не нужна абстракция для этих подсистем. И я не думаю, что синглтон подходит для этой ситуации - архитектура выглядит разбитой на части. Я хочу инициализировать все свои подсистемы в правильном порядке из одного места. Но существует слишком много ссылок на классы ...


ДОБАВЛЕНО
Глядя на DI - я могу отправлять зависимости конструктору класса и инициализировать каждый класс в статической фабрике. Это то, что я ищу.
Но я только что понял, что моя проблема в том, что когда я пытаюсь использовать объектно-компонентную архитектуру Unity3D, я не могу отправлять зависимости в конструктор, потому что инициализация класса вызывается из UnityEngine.
Итак, в этом случае мне нужен Singleton или Blob для хранения ссылок. если я выкину архитектуру Unity, я получу все зависимости от конструктора, и мне не понадобятся синглтоны или blob.
Мне нужно переделать мою архитектуру, чтобы UnityEngine не создавал объекты, которым нужно получать ссылки на подсистемы, но создавал эти классы из мой код и позволить им создавать свои «игровые объекты» UnityEngine и управлять ими.


person Vlad    schedule 08.06.2013    source источник
comment
Это также известно как The Blob - см. sourcemaking.com/antipatterns/the-blob. Возможная альтернатива - подумать о том, что делают ваши классы; у вас может быть PlayerManager с настройками игрока, сообщества и входа, WorldManager со всеми мировыми классами и EnvironmentManager для связанных классов. Каждый из них разбивает вашу проблему на более управляемые части. Затем вы также можете начать применять SRP - en.wikipedia.org/wiki/Single_responsibility_principle   -  person dash    schedule 09.06.2013
comment
Мне было бы любопытно услышать, почему вы считаете, что он ссылается на слишком много классов? Судя по вашему описанию, это кажется разумным решением описанной вами проблемы - инициализация в правильном порядке. Следующим лучшим подходом было бы разделение каждой подсистемы до такой степени, чтобы каждая подсистема могла компилироваться и функционировать независимо, что также облегчило бы тестирование :)   -  person Ben Brammer    schedule 09.06.2013
comment
Внедрение зависимостей - обычное решение, но вы уже отвергли это. Проблема не столько в Боге, сколько в том, как часто вы вызываете Его имя в своем коде. Вероятно, много, если у вас столько глобальных переменных. Так что, возможно, вам не стоит отказываться от DI.   -  person Hans Passant    schedule 09.06.2013
comment
@HansPassant, ты меня взбесишь, чувак! Я говорю вам. Теперь, что касается вас, Влад, почему бы не согласиться с тем, что говорит Ханс, сделать вашу жизнь немного проще, а затем использовать контейнер DI, такой как Unity, для инициализации и восстановить эти объекты. Видите ли, с контейнером вам не нужно буквально писать код для передачи всех зависимостей, контейнер делает это за вас, и он даже может обрабатывать пользовательские инициализации и синглтоны самостоятельно.   -  person Mike Perrenoud    schedule 09.06.2013
comment
Где упоминается неприязнь Влада к DI? Отредактировал ли он его во время льготного периода?   -  person Kirk Woll    schedule 09.06.2013
comment
@ Кирк Волл, я не редактировал. Я упомянул, что мне не нужны абстракции для этих подсистем, потому что они существуют только как один экземпляр и только с одной реализацией. Также сейчас я не собираюсь добавлять модульное тестирование для этих систем. И эта часть проекта не обязательно должна быть расширяемой.   -  person Vlad    schedule 09.06.2013


Ответы (2)


Глядя на DI - я могу отправлять зависимости конструктору класса и инициализировать каждый класс в статической фабрике. Это то, что я ищу. Но я только что понял, что моя проблема в том, что когда я пытаюсь использовать объектно-компонентную архитектуру Unity3D, я не могу отправлять зависимости конструктору, потому что инициализация класса вызывается из UnityEngine. Итак, в этом случае мне нужны Singleton или Blob для хранения ссылок. если я выброшу архитектуру Unity, я получу все зависимости от конструктора, и никаких одиночных или blob-объектов не потребуется. Мне нужно переработать мою архитектуру, чтобы UnityEngine не создавал объекты, которым необходимо получать ссылки на подсистемы, а создавал эти классы из моего кода и позволял им создавать свои «игровые объекты» UnityEngine и управлять ими.

person Vlad    schedule 13.06.2013

Я думаю, ты слишком много усложняешь, Влад.

Поскольку вашим менеджерам, контроллерам и прочим не нужно наследовать от MonoBehaviour, это становится простым случаем организации ваших подсистем в рамках одного объекта, который будет просто действовать как удобная точка доступа к ним.

Если у вас есть объекты-менеджеры, которым действительно требуется MonoBehaviour, эти ссылки можно получить из загруженной сцены с помощью простого события OnLevelLoaded или чего-то, что вы сами вызовете из любого объекта, который действительно запускает загрузку сцены. После запуска события используйте метод FindObjectOfType, предоставляемый Unity api, чтобы найти свои GameObject из сцены.

Итак, в конце дня один одноэлементный класс, известный как ваш объект God, будет отслеживать все ваши подсистемы, все, что связано со сценой, будет собираться из загруженной сцены с помощью простого вызова API.

Вот и все, что нужно сделать. Это может показаться сложным, но это не так.

person Alex    schedule 13.06.2013