Подтвердить что ты не робот

Что мы должны использовать вместо класса "manager" в хорошем дизайне ООП?

У меня возникли проблемы с разработкой моего игрового движка. Например:

Когда я думаю в Ресурсах, я думаю в классе ResourceManager для управления ресурсами на моем движке.

Этот класс получает несколько обязанностей:

  • Загрузка ресурсов.
  • Отображать ресурсы по идентификатору.
  • Убедитесь, что ресурсы загружены только один раз.
  • Бесплатные неиспользуемые ресурсы (с использованием интеллектуальных указателей).

Это работает для меня, но я прочитал в каждом учебном руководстве по ООП, что менеджеры - это двусмысленные классы с высокой связью и низкой связностью. Я понимаю это, и я согласен, но я искал почти весь Интернет, чтобы найти ясный пример реальной альтернативы менеджерам, но я не нашел его.

Некоторые объясняют, например, что ResourceManager следует разделить на более мелкие классы: ResourceFactory, ResourceCollection, ResourceCache, a ResourceFacade...

Я знаю все эти шаблоны проектирования (Factory, Collection, Facade и т.д.). Но я не понимаю, как это можно объединить, чтобы создать (легко управляемую) систему управления ресурсами.

Мой вопрос: Есть ли какой-нибудь учебник или документ с ясным примером? Может ли кто-нибудь объяснить пример этой системы? Я благодарю вас, если вы можете написать небольшой пример на С++ или на другом подобном языке.

Заранее благодарим за помощь!

4b9b3361

Ответ 1

Может быть:

  • Загрузка ресурсов → ResourceLoader
  • Отображать ресурсы по идентификатору → ResourceMapper
  • Убедитесь, что ресурсы загружаются только один раз → CachedResourceLoader/этот использует ResourceLoader, когда он еще не загружен.
  • Свободные неиспользуемые ресурсы (с использованием интеллектуальных указателей) → ?/не уверен в этом, но load + unload кажется очень сплоченными концепциями.

дополнительная информация в комментарии о "Бесплатные неиспользуемые ресурсы":

Во-первых, давайте ясно, что мы имеем только 2 из перечисленных выше: ResourceMapper и CachedResourceLoader. Поскольку экземпляр ResourceLoader используется из CachedResource, он не подвергается остальной части кода.

Обратите внимание, что следующее зависит от знания домена, поэтому я буду держать его открытым/вы узнаете, какие из них имеют смысл/относятся к вашим произведениям. Я бы сказал, что здесь есть 3 варианта:

  • ResourceMapper использует CachedResourceLoader, и вы только открываете предыдущий код для остальной части кода.
    • В этом подходе к ResourceMapper имеется единственная точка входа, поэтому имеет смысл, что он контролирует FreeUnused().
    • Как только он определяет, что он может освободить ресурс, он удалит его с карты. При необходимости он будет вызывать Unload для определенных элементов в CachedResourceLoader
  • Оба CachedResourceLoader и ResourceMapper используются вызывающим.
    • Если вам нужно только FreeUnused из ResourceMapper, просто добавьте его туда.
    • Если он должен быть освобожден от обоих, один из:
    • .FreeUnused в ResourceMapper получает файл cachedResourceLoader. После определения/удаления элементов с карты он передает список ресурсов, доступных для экземпляра cachedResourceLoader.
    • .FreeUnused в ResourceMapper возвращает список ресурсов, освобожденных от карты. Вызывающий звонит. Загрузите файл cachedResourceLoader, передав список ресурсов для выгрузки. Возможно, у вас есть приятное место в вызывающем устройстве, эти 2 звонка будут хорошо подходить.
  • Вы используете ResourceManager, но вместо того, чтобы иметь все реализации там, он использует ResourceMapper и CachedResourceLoader. Это было бы очень тонко, просто делая вызовы другим, в частности, вызовы .FreeUnused и .Unload в последней суб-марке выше.

Последнее замечание: Я считаю, что определенно стоит отделить обязанности и почувствовать себя сильными в этом. Тем не менее, это СОВЕРШЕННЫЕ принципы, за которыми я следую больше всего, я не запоминаю имена шаблонов и не обращаю внимания на такие правила, как классы менеджера, плохие.

Ответ 2

Ты уже сказал это уже:

Этот класс получает несколько обязанностей

(исходный акцент).

Это нарушает принцип единой ответственности. Кроме того, в слове Manager предлагается объект, который управляет другими объектами, что противоречит объектно-ориентированному принципу, что объекты должны инкапсулировать как данные, так и поведение. Это быстро приводит к запаху кода Feature Envy.

Разделение менеджера на многие более мелкие классы - правильная вещь. Чтобы сохранить их управляемость, вы можете реализовать Facade над ними.

Ответ 3

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

Другими словами, разложение класса на более мелкие классы, потому что более высокий класс имеет множественную ответственность, является хорошим принципом, но не законом. Вы не хотите следовать за ней любой ценой. Посмотрите на плюсы и минусы применения. Иногда разложение класса на более мелкие классы дает вам больший контроль над ответственностью, но за счет большой связи между этими классами. В вашем примере вы можете также реализовать различные классы для загрузки ресурсов, кеширования, сопоставления, сохранения и т.д. Но если каждому классу нужно поговорить с другими, чтобы выполнить свою работу, то разложение не стоит делать, потому что оно влечет за собой высокую сцепленность, что плохо; сохраните все в одном классе.

Иногда я думаю, что шаблоны дизайна нанесли столько же ущерба, сколько ясности для мира разработки программного обеспечения!: -)

Ответ 4

Я не думаю, что что-то не так с вашим решением. ИМХО, если вы думаете о том, что вы сказали с точки зрения Aspect Oriented Programming, это просто аспект ваших ресурсов, который будет обрабатываться классом.

Хотя, если вы думаете в целом, ваша база кода может развиваться в сотнях строк, поэтому было бы лучше разбить ваши функции инфраструктуры (шаблоны проектирования Driven Design).

Я думаю, что ваш класс является связным, а имя manager не всегда является плохим знаком, за исключением того, что он консолидирует поток управления из многих, возможно, несвязанных классов, которые взаимодействуют друг с другом для выполнения задачи.

Если ваши требования о кешировании и сопоставлении подвержены изменениям, возможно, было бы лучше Разделить свои проблемы.

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

Ответ 5

Я знаю все эти шаблоны проектирования (Factory, Collection, Facade и т.д.). Но я не понимаю, как это можно объединить, чтобы создать (легко управляемую) систему управления ресурсами.

Кто сказал, что их нужно объединить? Тогда ты вернулся туда, где начал, не так ли? Весь смысл разбить классы менеджера заключается в том, что вы получаете несколько более простых компонентов. Если вам нужна функция кеширования, вы разговариваете с кешем. Если вам нужна функция загрузки ресурсов, вы говорите с загрузчиком ресурсов.