Question

It's a little confusing that ZCML registrations for Zope utilities can accept a component or a factory.

<utility component=".some.Class" />

versus

<utility factory=".some.Factory" />

What is the difference?

Was it helpful?

Solution

A factory creates utilities, while a utility registered as a component is an instance. Hence, if you look up a utility registered as a component, you will get the same object back every time. But if it's registered as a factory, you'll get a new instance every time.

OTHER TIPS

I think @lennart-regebro's answer might be a little unintentionally deceptive. It's understandable as the zope docs are a little vague. I think below is the correct interpretation but I had to test it myself to be sure.

In both the component and the factory registration each subsequent call to getUtility, after an initial registration, will return the same instance.

The difference is that the component method will register the referenced object as the utility instance to be returned, where as the factory method will call the referenced object and store the result as the utility instance to be returned.

Factory Example

So for example if you have a utility class defined as thus;

class MyUtility(object):
    implements(IMyUtility)
    ...

registering it with; <utility factory=".my_module.MyUtility"/>

will at the point the zcml is executed create an instance of MyUtility and store it for any future calls to getUtility;

> a = getUtility(IMyUtility)
> b = getUtility(IMyUtility)
> c = getUtility(IMyUtility)
> a is b is c
True

Note that we could have registered the factory to be a function instead of a class, it just has to be something that when called with no arguments returns the instance of your utility you want to use.

Component Example

An equivalent example with component is;

class MyUtility(object):
    implements(IMyUtility)
    ...

my_module_instance_of_utility = MyUtility()

registering it with; <utility component=".my_module.my_module_instance_of_utility"\>

This is more or less equivalent to the factory example. The only difference is that the instance returned in the component example is instantiated when my_module is imported by anything (including the registration mechanism), where as when using a factory the instance is instantiated when the zcml config is executed, just before it's registered. In both cases subsequent calls to getUtility will return the same instance.

Not to be confused with IFactory

None of this is to be confused with IFactory which does provide something which can provide you a new instance each time it's asked for but with a slightly different API. See this document for more information about those.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top