Factory of Factories pattern¶
This example demonstrates “Factory of Factories” pattern.
The idea of the pattern is in creating a Factory
that creates another Factory
and adds
additional arguments.
base_factory = providers.Factory(
providers.Factory
SomeClass,
base_argument=1,
)
concrete_factory = providers.Factory(
OtherClass,
instance=base_factory(extra_argument=1),
)
if __name__ == "__main__":
instance = concrete_factory()
# Same as: # instance = SomeClass(base_argument=1, extra_argument=2)
Sample code¶
Listing of the pattern example:
"""`Factory of Factories` pattern."""
from dependency_injector import containers, providers
class SqlAlchemyDatabaseService:
def __init__(self, session, base_class):
self.session = session
self.base_class = base_class
class TokensService:
def __init__(self, id_generator, database):
self.id_generator = id_generator
self.database = database
class Token:
...
class UsersService:
def __init__(self, id_generator, database):
self.id_generator = id_generator
self.database = database
class User:
...
# Sample objects
session = object()
id_generator = object()
class Container(containers.DeclarativeContainer):
database_factory = providers.Factory(
providers.Factory,
SqlAlchemyDatabaseService,
session=session,
)
token_service = providers.Factory(
TokensService,
id_generator=id_generator,
database=database_factory(base_class=Token),
)
user_service = providers.Factory(
UsersService,
id_generator=id_generator,
database=database_factory(base_class=User),
)
if __name__ == "__main__":
container = Container()
token_service = container.token_service()
assert token_service.database.base_class is Token
user_service = container.user_service()
assert user_service.database.base_class is User
Arguments priority¶
Passing of the arguments works the same way like for any other Factory provider.
# 1. Keyword arguments of upper level factory are added to lower level factory
factory_of_dict_factories = providers.Factory(
providers.Factory,
dict,
arg1=1,
)
dict_factory = factory_of_dict_factories(arg2=2)
print(dict_factory()) # prints: {"arg1": 1, "arg2": 2}
# 2. Keyword arguments of upper level factory have priority
factory_of_dict_factories = providers.Factory(
providers.Factory,
dict,
arg1=1,
)
dict_factory = factory_of_dict_factories(arg1=2)
print(dict_factory()) # prints: {"arg1": 2}
# 3. Keyword arguments provided from context have the most priority
factory_of_dict_factories = providers.Factory(
providers.Factory,
dict,
arg1=1,
)
dict_factory = factory_of_dict_factories(arg1=2)
print(dict_factory(arg1=3)) # prints: {"arg1": 3}
Credits¶
The “Factory of Factories” pattern was suggested by the Dependency Injector
users.