В таких ситуациях я успешно ввел (повторно использовал) термин «контекст», иногда с несколькими слоями.
Это означает одноэлементное, то есть «глобальное» хранилище объектов, из которого могут быть запрошены объекты такого типа. Коды, которые требуют их, включают в себя заголовок хранилища и используют глобальные функции для получения экземпляров своих объектов (как, например, поставщик процентных ставок).
Магазин может быть:
- строго типизированный: вы включаете заголовки для всех обслуживаемых типов и, таким образом, можете создавать типизированные методы доступа, такие как InterestRate getCurrentInterestRate ();
- или универсальный: объект getObject (enum obType); и только расширяйте перечисление obType новыми видами (obtypeCurrentInterestRate).
Чем больше система, тем более пригодно последнее решение для довольно небольшого риска использования неправильного перечисления. С другой стороны, с языками, которые допускают прямое объявление типов, я думаю, что вы можете использовать типизированные средства доступа без включения всех заголовков в хранилище.
Еще одно примечание: у вас может быть несколько экземпляров одного и того же типа объекта для разных целей, например, иногда разные значения языка для графического интерфейса пользователя, а также для журналов распечатки, глобального уровня и журнала сеанса и т. Д., Поэтому имя перечисления / средства доступа НЕ должно отражать фактический тип , но роль запрошенного экземпляра (CurrentInterestRate).
В реализации магазина вы должны управлять уровнями контекста и коллекциями экземпляров контекста. Простым примером является веб-служба, где у вас есть глобальный контекст (один экземпляр для всех запросов для этого объекта - проблемный при наличии фермы серверов) и контекст для каждого веб-сеанса. Вы также можете иметь контексты для каждого пользователя, который может иметь несколько параллельных сессий и т. Д. С несколькими серверами вы должны использовать своего рода распределенный кеш для таких вещей.
Когда приходит запрос, вы решаете, на каком уровне контекста находится запрошенный объект, получите этот контекст для вызова. Если объект есть, вы отправляете его обратно; если нет, вы создаете и сохраняете его на этом уровне контекста и возвращаете его. Конечно, синхронизировать раздел создания (и опубликовать его в распределенном кеше). Создание может быть настраиваемым, как плагин, лучше всего с языками, позволяющими создавать экземпляры объектов по имени их класса (Java, Objective C, ...), но вы можете сделать это и в C с подключаемыми библиотеками, имеющими фабричные функции.
Примечание: вызывающий объект НЕ должен знать слишком много о своих собственных контекстах и уровне контекста запрашиваемого объекта. Причины: 1: легко допустить ошибку (или «умные трюки»), играя с этими параметрами; 2: уровень контекста запрошенного может измениться позже. Я в основном подключаю контекстную информацию к потоку, поэтому хранилище объектов содержит информацию без дополнительных параметров из запроса.
С другой стороны, запрос может содержать подсказку для экземпляра: например, получение процентной ставки на определенную дату. Это должен быть один и тот же «глобальный» доступ, но несколько экземпляров в зависимости от даты (и приведение разных значений даты к одному и тому же экземпляру между изменениями курса), поэтому рекомендуется добавить в запрос объект «подсказка», используемый экземпляр фабрики а не магазина; и keyForHint для фабрики, используемой магазином. Вы можете добавить эти функции позже, я только что упомянул.
В вашем случае это является своего рода излишним (на глобальном уровне обслуживается только один объект), но для совсем небольшого и простого дополнительного кода прямо сейчас вы получаете механизм для дальнейших, возможно, более сложных требований.
Еще одна хорошая новость: если вы находитесь на Java, вы получаете этот сервис от Spring, не задумываясь, я просто хотел объяснить это подробнее.