Factory Example

In this example you’ll see how we can declare a function as a factory of injectable instances.

A common use case for using factories is to wrap some class external to your code or which you cannot declare as injectable for some reason, we declare a ExternalClient class to represent such a case.

The client_factory function is declared as a factory for the ExternalClient class through the @injectable_factory decorator and will deal with all the necessary logic to instantiate an ExternalClient.

Now our Factory example class can be injected with an ExternalClient without having the responsibility of knowing how to actually instantiate it.

See also

The injectable_factory decorator can also be used in lambdas for simpler cases. The Injecting Existing Instance Example shows how to use it like so.

factory_example.py
from examples import Example
from examples.factory.external_client import ExternalClient
from injectable import autowired, Autowired, load_injection_container


class Factory(Example):
    @autowired
    def __init__(
        self,
        client: Autowired(ExternalClient),
    ):
        self.client = client

    def run(self):
        print(self.client.connect())
        # ExternalClient connected to https://dummy/endpoint


def run_example():
    load_injection_container()
    example = Factory()
    example.run()


if __name__ == "__main__":
    run_example()
client_factory.py
import os

from examples.factory.external_client import ExternalClient
from injectable.injection.injectable_factory_decorator import injectable_factory


@injectable_factory(ExternalClient)
def client_factory():
    client_endpoint = os.getenv(
        "CLIENT_ENDPOINT_EXAMPLE_ENV_VAR", "https://dummy/endpoint"
    )
    return ExternalClient(client_endpoint)
external_client.py
class ExternalClient:
    def __init__(self, endpoint: str):
        self.endpoint = endpoint

    def connect(self):
        return f"ExternalClient connected to {self.endpoint}"