В чем разница между утилитой Zope, определенной с помощью фабрики, и компонентом?
-
22-09-2019 - |
Вопрос
Немного сбивает с толку тот факт, что регистрации ZCML для Zope utilities могут принимать компонент или фабрику.
<utility component=".some.Class" />
против
<utility factory=".some.Factory" />
В чем же разница?
Решение
Фабрика создает утилиты, в то время как утилита, зарегистрированная как компонент, является экземпляром.Следовательно, если вы отыщете утилиту, зарегистрированную как компонент, вы будете каждый раз получать один и тот же объект обратно.Но если он зарегистрирован как factory, вы будете каждый раз получать новый экземпляр.
Другие советы
Я думаю, что ответ @lennart-regebro может быть немного непреднамеренно вводящим в заблуждение.Это понятно, поскольку документы zope немного расплывчаты.Я думаю, что ниже приведена правильная интерпретация, но мне пришлось проверить это самому, чтобы убедиться.
В как компонент, так и завод Регистрация каждый последующий вызов для getUtility, после первоначальной регистрации, вернет тот же экземпляр.
Разница заключается в том, что метод component зарегистрирует объект, на который ссылается, как экземпляр утилиты, подлежащий возврату, где в качестве фабричного метода будет вызван объект, на который ссылается, и сохранен результат как экземпляр утилиты, подлежащий возврату.
Заводской Пример
Так, например, если у вас есть служебный класс, определенный таким образом;
class MyUtility(object):
implements(IMyUtility)
...
регистрируя его с; <utility factory=".my_module.MyUtility"/>
будет ли в момент выполнения zcml создан экземпляр MyUtility и сохранен ли он для любых будущих вызовов getUtility;
> a = getUtility(IMyUtility)
> b = getUtility(IMyUtility)
> c = getUtility(IMyUtility)
> a is b is c
True
Обратите внимание, что мы могли бы зарегистрировать factory как функцию, а не класс, это просто должно быть что-то, что при вызове без аргументов возвращает экземпляр вашей утилиты, которую вы хотите использовать.
Пример компонента
Эквивалентным примером с компонентом является;
class MyUtility(object):
implements(IMyUtility)
...
my_module_instance_of_utility = MyUtility()
регистрируя его с; <utility component=".my_module.my_module_instance_of_utility"\>
Это более или менее эквивалентно заводскому примеру.Единственное отличие заключается в том, что экземпляр, возвращаемый в примере компонента, создается, когда my_module
импортируется чем угодно (включая механизм регистрации), где, как и при использовании фабрики, экземпляр создается при выполнении конфигурации zcml, непосредственно перед его регистрацией.В обоих случаях последующие вызовы getUtility вернут один и тот же экземпляр.
Не путать с IFactory
Ничто из этого не следует путать с IFactory, который предоставляет что-то, что может предоставлять вам новый экземпляр каждый раз, когда его запрашивают, но с немного другим API.Видишь этот документ для получения дополнительной информации о тех.