Edit abstract factory section

This commit is contained in:
Roman Mogylatov 2020-08-31 18:43:17 -04:00
parent 091dc128fd
commit 452c77cadd
5 changed files with 86 additions and 92 deletions

View File

@ -104,44 +104,24 @@ class attribute.
:lines: 3-
:emphasize-lines: 12-14
.. _abstract_factory_providers:
Abstract factory
~~~~~~~~~~~~~~~~
Abstract factory providers
~~~~~~~~~~~~~~~~~~~~~~~~~~
:py:class:`AbstractFactory` provider helps when you need to create a provider of some base class
and the particular implementation is not yet know. ``AbstractFactory`` provider is a ``Factory``
provider with two peculiarities:
:py:class:`AbstractFactory` provider is a :py:class:`Factory` provider that
must be explicitly overridden before calling.
+ Provides only objects of a specified type.
+ Must be overridden before usage.
.. note::
Overriding of :py:class:`AbstractFactory` provider is possible only by
another :py:class:`Factory` provider.
:py:class:`AbstractFactory` provider is useful when it is needed to specify
explicitly that it only provides abstraction, but not an implementation.
Client code must override such factories with factories that provide particular
implementations. Otherwise, :py:class:`AbstractFactory` will raise an error
on attempt of calling it. At the same time, :py:class:`AbstractFactory` is
regular provider that could be injected into other providers (or used for
any other kind of bindings) without being overridden. After
:py:class:`AbstractFactory` provider has been overridden, its behaviour is
identical to regular :py:class:`Factory` provider.
Example:
.. image:: /images/providers/abstract_factory.png
.. image:: images/abstract_factory.png
:width: 100%
:align: center
Listing of ``cache.py``:
.. literalinclude:: ../../examples/providers/abstract_factory/cache.py
:language: python
Listing of ``example.py``:
.. literalinclude:: ../../examples/providers/abstract_factory/example.py
.. literalinclude:: ../../examples/providers/abstract_factory.py
:language: python
:lines: 3-
:emphasize-lines: 32
Factory aggregate providers
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,75 @@
"""`AbstractFactory` providers example."""
import abc
import dataclasses
import random
from typing import List
from dependency_injector import providers
class AbstractCacheClient(metaclass=abc.ABCMeta):
...
@dataclasses.dataclass
class RedisCacheClient(AbstractCacheClient):
host: str
port: int
db: int
@dataclasses.dataclass
class MemcachedCacheClient(AbstractCacheClient):
hosts: List[str]
port: int
prefix: str
@dataclasses.dataclass
class Service:
cache: AbstractCacheClient
cache_client_factory = providers.AbstractFactory(AbstractCacheClient)
service_factory = providers.Factory(
Service,
cache=cache_client_factory,
)
if __name__ == '__main__':
cache_type = random.choice(['redis', 'memcached', None])
if cache_type == 'redis':
cache_client_factory.override(
providers.Factory(
RedisCacheClient,
host='localhost',
port=6379,
db=0,
),
)
elif cache_type == 'memcached':
cache_client_factory.override(
providers.Factory(
MemcachedCacheClient,
hosts=['10.0.1.1'],
port=11211,
prefix='my_app',
),
)
service = service_factory()
print(service.cache)
# The output depends on cache_type variable value.
#
# If the value is 'redis':
# RedisCacheClient(host='localhost', port=6379, db=0)
#
# If the value is 'memcached':
# MemcachedCacheClient(hosts=['10.0.1.1'], port=11211, prefix='my_app')
#
# If the value is None:
# Error: AbstractFactory(<class '__main__.AbstractCacheClient'>) must be
# overridden before calling

View File

@ -1,25 +0,0 @@
"""Example hierarchy of cache clients with abstract base class."""
class AbstractCacheClient:
"""Abstract cache client."""
class RedisCacheClient(AbstractCacheClient):
"""Cache client implementation based on Redis."""
def __init__(self, host, port, db):
"""Initialize instance."""
self.host = host
self.port = port
self.db = db
class MemcacheCacheClient(AbstractCacheClient):
"""Cache client implementation based on Memcached."""
def __init__(self, hosts, port, prefix):
"""Initialize instance."""
self.hosts = hosts
self.port = port
self.prefix = prefix

View File

@ -1,36 +0,0 @@
"""`AbstractFactory` providers example."""
import cache
import dependency_injector.providers as providers
# Define abstract cache client factory:
cache_client_factory = providers.AbstractFactory(cache.AbstractCacheClient)
if __name__ == '__main__':
# Override abstract factory with redis client factory:
cache_client_factory.override(
providers.Factory(
cache.RedisCacheClient,
host='localhost',
port=6379,
db=0,
),
)
redis_cache = cache_client_factory()
print(redis_cache)
# <cache.RedisCacheClient object at 0x10975bc50>
# Override abstract factory with memcache client factory:
cache_client_factory.override(
providers.Factory(
cache.MemcacheCacheClient,
hosts=['10.0.1.1', '10.0.1.2', '10.0.1.3'],
port=11211,
prefix='my_app',
),
)
memcache_cache = cache_client_factory()
print(memcache_cache)
# <cache.MemcacheCacheClient object at 0x10975bc90>