Внезапно у меня немного критический кризис. За последние пару лет я неплохо использовал объекты Singleton. Я использовал их во многих местах.Хороший дизайн OO - Шаблон дизайна Singleton
Например, при разработке Java-приложения MVC я бы создал класс Singleton 'SystemRegistry' для хранения моделей и классов классов (я работал только с простыми приложениями, и необходимость в нескольких представлениях никогда не возникала) ,
Когда я создаю свои модели и просматривать объекты (которые не были одиночками, просто нормальные объекты), я бы что-то вроде:
SystemRegistry.getInstance().setModel(model);
В моих классах контроллеров (которые были в значительной степени обработчиков событий для разные Gui элементы), я хотел бы получить доступ к представлению или модели следующим образом:
SystemRegistry.getInstance().getView();
Я никогда бы не использовать класс SystemRegistry в модельной части моего приложения, но будет, время от времени, использовать его на мой взгляд, для доступа (но редко, если вообще, для изменения) информации из модели.
Из того, что я читал (в частности, Steve Yegge's article), это кажется плохим способом разработки моего приложения. Любые идеи относительно лучшего способа структурирования моего кода.
Кроме того, еще один аспект того, как я проектирую классы, которые могут или не могут быть связаны с Singletons, - это использование классов «Тип менеджера». Примером является (очень простой) движок игры на OpenGL, созданный на C++.
Основным классом был GameEngine. Это был класс over-arcing, который хранил кучу менеджеров и обрабатывал основной цикл, а что нет. Некоторые из менеджеров, хранящихся в этом классе, были такими, как: ObjectManager, RenderingManager, LightingManager, EventManager (включая ввод), HUDManager, FrameRateManager, WindowManager и т. Д. Возможно, было еще несколько.
В основном эти классы обрабатывали различные аспекты игрового движка. Имена довольно просты, поэтому вы должны иметь представление о том, как они используются.
Теперь это должно быть многоразовой базой, которую я мог бы использовать в разных проектах, с необходимостью ее идеального изменения.
В каждой новой игре я бы создал экземпляр GameEngine как переменной класса (большая часть игровой логики хранилась в одном классе) и настраивала разных менеджеров (например, загружая окно co -определяет или освещает детали из файла, устанавливая FPS и т. д.). Для того, чтобы зарегистрировать объект в ObjectManager я хотел бы сделать что-то вроде:
Player player = new Player();
gameEngine.getObjectManager().addObject(player);
Этот объект теперь будет храниться в векторе в классе ObjectManager и будет нарисована, когда GameEngine вызывает метод() в каждом кадре в ObjectManager drawObjects ,
Я, возможно, получил немного параноиков после этой статьи в Singletons (и, возможно, не хватило времени, чтобы обернуть вокруг меня голову), но я начинаю вторгаться и задаюсь вопросом, способ, которым я проектировал свои GameEngine был правильным (из-за отсутствия лучшего слова) и не просто попадал в те же ловушки, которые разделял шаблон Singleton.
Любые комментарии к моему сообщению будут высоко оценены.
Редактировать: Спасибо за ответы. Я их очень ценю.Если возможно, мне бы хотелось, чтобы кто-то мог дать мне несколько советов относительно двух сценариев проекта, опубликованных выше. Как я мог избежать использования синглтонов/менеджеров?
С первым, будет ли DI правильным ответом? Должен ли я даже дать виду доступ к модели (вероятно, это скорее ответ MVC)? Будет ли представление выгодно реализовать интерфейс (чтобы можно было подключить несколько разных представлений)?
Во втором случае, как еще можно было структурировать приложение? Является ли gripe просто использованием классов Manager в отличие от более конкретных имен? Или в некоторых случаях классы могут быть дополнительно разбиты (например, ObjectHolder, ObjectDrawer, ObjectUpdater)?
+1 «Винт ООП» - это глоток свежего воздуха. Слишком много людей автоматически и безоговорочно приравнивают «ООП» к «хорошему». Бьярне Страуструп писал об этом не один раз. – fredoverflow
Я не понимаю, «хорошая вещь об этом подходе, по сравнению с DI, заключается в том, что вы делаете свои зависимости болезненно явными». Это то, что вы делаете в DI; ваши классы задают свои зависимости либо в параметрах конструктора, и в установках, либо в (yick) частных переменных.Вы можете сделать это без DI _framework_, но это может быть сложно. Выполнение этого вручную часто приводит к тому, что класс A принимает класс B в конструкторе, когда единственное использование B - передать его конструктору класса C. – NamshubWriter
@NamshubWriter: я считаю, что с картой DI класс регистрирует свои зависимости , конечно, и тогда они как бы «волшебным образом появляются». Вам не нужно передавать их с того места, где они созданы, где они нужны, поэтому вы не можете «почувствовать» зависимость, как вы делаете, если единственный способ распространения зависимостей - передать их как параметры. DI затрудняет просмотр информации о том, откуда появилась зависимость *. И это не дает вам четкого способа отслеживать, где определенный объект используется как зависимость. Все зависит от большого черного ящика глобального состояния, которое свободно распространяется на зависимости. – jalf