cybertools/util/adapter.txt
helmutm 872fccc529 added some experimental stuff for self-registering adapters using a metaclass
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2465 fd906abe-77d9-0310-91a1-e0d9ade77398
2008-03-21 13:11:12 +00:00

125 lines
3.4 KiB
Text

==========================
A Simple Adapter Framework
==========================
$Id$
To work with adapters we need at least two classes, one for objects
that we want to adapt to (the adapter's `context`) and one for the adapters.
Adapter Classes and Factories
=============================
>>> class Content(object):
... pass
>>> class StateAdapter(object):
... def __init__(self, context):
... self.context = context
... def setState(self, state):
... self.context._state = state
... def getState(self):
... return getattr(self.context, '_state', 'initial')
In order to use the adapters in a flexible way we create adapter objects
by using an adapter factory. The stateful factory is intended to create
adapters that allow setting and retrieving the state of objects.
>>> from cybertools.util.adapter import AdapterFactory
>>> stateful = AdapterFactory()
We can now register our StateAdapter class with the `stateful` AdapterFactory.
We have to tell the factory which class of adapted objects a certain
adapter class is responsible for.
>>> stateful.register(StateAdapter, Content)
Now we are ready to create an object of the Content class
>>> c1 = Content()
and a corresponding `stateful` adapter:
>>> c1State = stateful(c1)
The adapter can now be used to access the Content object's state:
>>> c1State.getState()
'initial'
>>> c1State.setState('visible')
>>> c1State.getState()
'visible'
The procedure also works with subclasses of the Content class.
>>> class SpecialContent(Content):
... pass
>>> sc1 = SpecialContent()
>>> sc1State = stateful(sc1)
>>> sc1State.getState()
'initial'
>>> sc1State.setState('public')
>>> sc1State.getState()
'public'
But if we try to use an adapter factory for objects for which there is
no adapter registered we get back None.
>>> class UnknownContent(object):
... pass
>>> uc1 = UnknownContent()
>>> uc1State = stateful(uc1)
>>> uc1State is None
True
Class adapters as factories
---------------------------
There is a special case that can be handled with an adapter factory:
creating objects via an adapter to a class. An example for this is
a class that creates objects by loading them from a file or database,
so this would be a storage adapter class.
In our example we avoid reading from disk or from a database but just
create the object wanted by using the context's constructor.
>>> class ContentLoader(object):
... def __init__(self, context):
... self.context = context
... def load(self):
... return Content()
>>> storage = AdapterFactory()
>>> storage.register(ContentLoader, Content)
In this case we get the adapter from the adapter factory by providing
it with the context class (instead of an instance of it like in the
example above.
>>> loader = storage(Content)
>>> c2 = loader.load()
>>> c2
<Content object ...>
Self-registering Adapters
=========================
>>> from cybertools.util.adapter import adapters, AdapterBase
>>> stateful = AdapterFactory()
>>> class StateAdapter(AdapterBase):
... __adapterinfo__ = stateful, Content
... def __init__(self, context):
... self.context = context
... def setState(self, state):
... self.context._state = state
... def getState(self):
... return getattr(self.context, '_state', 'initial')
>>> stateful._registry
{(<class 'Content'>, ''): <class 'StateAdapter'>}