В чем разница между утилитой Zope, определенной в фабрике, и компонентом?
Немного сбивает с толку тот факт, что для регистрации ZCML для утилит Zope можно принять компонент или фабрику.
<utility component=".some.Class" />
против
<utility factory=".some.Factory" />
В чем разница?
2 ответа
Фабрика создает утилиты, а утилита, зарегистрированная как компонент, является экземпляром. Следовательно, если вы посмотрите утилиту, зарегистрированную как компонент, вы будете возвращать один и тот же объект каждый раз. Но если он зарегистрирован как фабрика, вы будете получать новый экземпляр каждый раз.
Я думаю, что ответ @ lennart-regebro может быть немного непреднамеренно обманчивым. Это понятно, так как документы Zope немного расплывчаты. Я думаю, что ниже приведена правильная интерпретация, но я должен был проверить это сам, чтобы быть уверенным.
И в регистрации компонента, и в заводской регистрации каждый последующий вызов getUtility после первоначальной регистрации возвращает один и тот же экземпляр.
Разница заключается в том, что метод компонента зарегистрирует указанный объект как экземпляр утилиты, который будет возвращен, тогда как фабричный метод вызовет указанный объект и сохранит результат в качестве возвращаемого экземпляра утилиты.
Пример фабрики
Например, если у вас есть служебный класс, определенный следующим образом;
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
Обратите внимание, что мы могли бы зарегистрировать фабрику как функцию вместо класса, просто она должна быть чем-то, что при вызове без аргументов возвращает экземпляр вашей утилиты, которую вы хотите использовать.
Пример компонента
Эквивалентный пример с компонентом:
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. Смотрите этот документ для получения дополнительной информации о них.