В чем разница между утилитой 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. Смотрите этот документ для получения дополнительной информации о них.

Другие вопросы по тегам