mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 09:57:37 +03:00 
			
		
		
		
	Edit abstract factory section
This commit is contained in:
		
							parent
							
								
									091dc128fd
								
							
						
					
					
						commit
						452c77cadd
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								docs/providers/images/abstract_factory.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/providers/images/abstract_factory.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 24 KiB  | 
							
								
								
									
										75
									
								
								examples/providers/abstract_factory.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								examples/providers/abstract_factory.py
									
									
									
									
									
										Normal 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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user