Factory Method
Definition
Section titled “Definition”The Factory Method pattern delegates object creation to subclasses or specialized methods, allowing the type of created object to vary without modifying calling code. The caller works with the interface; the factory selects the concrete implementation.
Diagram
Section titled “Diagram”classDiagram
class VaultClientFactory {
+Create() IVaultClient
}
class IVaultClient {
<<interface>>
}
class KubernetesAuthClient
class TokenAuthClient
VaultClientFactory ..> IVaultClient : creates
IVaultClient <|.. KubernetesAuthClient
IVaultClient <|.. TokenAuthClient
class ITenantIsolationStrategyProvider {
+Create() DbContext
}
class SharedDatabaseDbContextFactory
class TenantPerSchemaDbContextFactory
class TenantPerDatabaseDbContextFactory
ITenantIsolationStrategyProvider <|.. SharedDatabaseDbContextFactory
ITenantIsolationStrategyProvider <|.. TenantPerSchemaDbContextFactory
ITenantIsolationStrategyProvider <|.. TenantPerDatabaseDbContextFactory
Implementation in Granit
Section titled “Implementation in Granit”| Factory | File | Selection |
|---|---|---|
VaultClientFactory | src/Granit.Vault/Services/VaultClientFactory.cs | Switch expression on AuthMethod (Kubernetes / Token) |
SharedDatabaseDbContextFactory | src/Granit.Persistence/MultiTenancy/SharedDatabaseDbContextFactory.cs | SharedDatabase strategy |
TenantPerSchemaDbContextFactory | src/Granit.Persistence/MultiTenancy/TenantPerSchemaDbContextFactory.cs | SchemaPerTenant strategy |
TenantPerDatabaseDbContextFactory | src/Granit.Persistence/MultiTenancy/TenantPerDatabaseDbContextFactory.cs | DatabasePerTenant strategy |
Custom variant: the persistence factories combine Factory Method +
Strategy — the strategy is selected at configuration time, and the factory
creates the appropriate DbContext per request.
Rationale
Section titled “Rationale”The choice of Vault authentication method (Kubernetes in production, Token in
development) and tenant isolation strategy must be resolved at runtime
without if/else in application code.
Usage example
Section titled “Usage example”// The factory is resolved via DI -- calling code is unaware of the implementationIVaultClient client = vaultClientFactory.Create();SecretData secret = await client.V1.Secrets.KeyValue.V2 .ReadSecretAsync("app/database", cancellationToken: ct);