0
# Factory Functions
1
2
Advanced factory utilities for creating sophisticated dependency construction patterns with caching strategies, conditional instantiation, and performance optimization.
3
4
## Capabilities
5
6
### Factory Function Type
7
8
Base factory function signature used throughout the factory system.
9
10
```typescript { .api }
11
/**
12
* Factory function signature for creating instances
13
* Receives dependency container for accessing other dependencies
14
* @param dependencyContainer - Container for resolving dependencies
15
* @returns Instance of type T
16
*/
17
type FactoryFunction<T> = (dependencyContainer: DependencyContainer) => T;
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
// Basic factory function
24
const loggerFactory: FactoryFunction<Logger> = (container) => {
25
const config = container.resolve<LogConfig>("LogConfig");
26
return new Logger(config.level, config.format);
27
};
28
29
// Complex factory with multiple dependencies
30
const databaseFactory: FactoryFunction<Database> = (container) => {
31
const config = container.resolve<DatabaseConfig>("DatabaseConfig");
32
const logger = container.resolve<Logger>("Logger");
33
const connectionPool = container.resolve<ConnectionPool>("ConnectionPool");
34
35
const db = new Database(config.connectionString);
36
db.setLogger(logger);
37
db.setConnectionPool(connectionPool);
38
39
return db;
40
};
41
42
// Register factory
43
container.register("Database", { useFactory: databaseFactory });
44
```
45
46
### Global Instance Caching
47
48
Factory wrapper that caches instances globally across all containers and resolution calls.
49
50
```typescript { .api }
51
/**
52
* Creates factory that caches instance globally
53
* Instance is shared across all containers and resolution calls
54
* Perfect for expensive-to-create singletons
55
* @param factoryFunc - Base factory function to wrap
56
* @returns Cached factory function
57
*/
58
function instanceCachingFactory<T>(factoryFunc: FactoryFunction<T>): FactoryFunction<T>;
59
```
60
61
**Usage Examples:**
62
63
```typescript
64
// Expensive service that should be created only once globally
65
const expensiveServiceFactory: FactoryFunction<ExpensiveService> = (container) => {
66
console.log("Creating expensive service (this should only happen once)");
67
const config = container.resolve<ServiceConfig>("ServiceConfig");
68
return new ExpensiveService(config);
69
};
70
71
// Wrap with global caching
72
const cachedFactory = instanceCachingFactory(expensiveServiceFactory);
73
74
// Register cached factory
75
container.register("ExpensiveService", { useFactory: cachedFactory });
76
77
// Multiple containers share same instance
78
const container1 = container.createChildContainer();
79
const container2 = container.createChildContainer();
80
81
const service1 = container1.resolve<ExpensiveService>("ExpensiveService");
82
const service2 = container2.resolve<ExpensiveService>("ExpensiveService");
83
// service1 === service2 (same instance)
84
85
// Configuration service example
86
const configFactory = instanceCachingFactory<Configuration>((container) => {
87
console.log("Loading configuration from file...");
88
return Configuration.loadFromFile("./config.json");
89
});
90
91
container.register("Configuration", { useFactory: configFactory });
92
```
93
94
### Container-Scoped Caching
95
96
Factory wrapper that caches instances per container, allowing different instances in child containers while maintaining caching within each container scope.
97
98
```typescript { .api }
99
/**
100
* Creates factory that caches instance per container
101
* Each container maintains its own cached instance
102
* Child containers can have different instances than parents
103
* @param factoryFunc - Base factory function to wrap
104
* @returns Per-container cached factory function
105
*/
106
function instancePerContainerCachingFactory<T>(factoryFunc: FactoryFunction<T>): FactoryFunction<T>;
107
```
108
109
**Usage Examples:**
110
111
```typescript
112
// Request context that should be unique per container (e.g., per HTTP request)
113
const requestContextFactory: FactoryFunction<RequestContext> = (container) => {
114
console.log("Creating request context for container");
115
const requestId = container.resolve<string>("RequestId");
116
const userId = container.resolve<string>("UserId");
117
return new RequestContext(requestId, userId);
118
};
119
120
// Wrap with per-container caching
121
const perContainerCachedFactory = instancePerContainerCachingFactory(requestContextFactory);
122
123
container.register("RequestContext", { useFactory: perContainerCachedFactory });
124
125
// Parent container has one instance
126
const parentContext = container.resolve<RequestContext>("RequestContext");
127
const sameParentContext = container.resolve<RequestContext>("RequestContext");
128
// parentContext === sameParentContext
129
130
// Child containers have their own instances
131
const childContainer1 = container.createChildContainer();
132
const childContainer2 = container.createChildContainer();
133
134
const child1Context = childContainer1.resolve<RequestContext>("RequestContext");
135
const child2Context = childContainer2.resolve<RequestContext>("RequestContext");
136
// child1Context !== child2Context !== parentContext
137
138
// Database connection pool per environment
139
const dbPoolFactory = instancePerContainerCachingFactory<ConnectionPool>((container) => {
140
const env = container.resolve<string>("Environment");
141
console.log(`Creating connection pool for ${env}`);
142
return new ConnectionPool(`db-${env}.example.com`);
143
});
144
145
container.register("ConnectionPool", { useFactory: dbPoolFactory });
146
```
147
148
### Predicate-Aware Class Factory
149
150
Advanced factory that conditionally chooses between different constructors based on runtime conditions, with optional caching support.
151
152
```typescript { .api }
153
/**
154
* Creates factory that chooses constructor based on predicate
155
* Enables conditional instantiation patterns
156
* @param predicate - Function determining which constructor to use
157
* @param trueConstructor - Constructor used when predicate returns true
158
* @param falseConstructor - Constructor used when predicate returns false
159
* @param useCaching - Whether to cache instances (default: false)
160
* @returns Conditional factory function
161
*/
162
function predicateAwareClassFactory<T>(
163
predicate: (dependencyContainer: DependencyContainer) => boolean,
164
trueConstructor: constructor<T>,
165
falseConstructor: constructor<T>,
166
useCaching?: boolean
167
): FactoryFunction<T>;
168
```
169
170
**Usage Examples:**
171
172
```typescript
173
// Environment-based service selection
174
const isProduction = (container: DependencyContainer) => {
175
const env = container.resolve<string>("Environment");
176
return env === "production";
177
};
178
179
const loggerFactory = predicateAwareClassFactory(
180
isProduction,
181
ProductionLogger, // Use in production
182
DevelopmentLogger, // Use in development
183
true // Cache the instance
184
);
185
186
container.register("Logger", { useFactory: loggerFactory });
187
188
// Feature flag based implementation
189
const hasFeatureFlag = (container: DependencyContainer) => {
190
const featureFlags = container.resolve<FeatureFlags>("FeatureFlags");
191
return featureFlags.isEnabled("new-payment-processor");
192
};
193
194
const paymentProcessorFactory = predicateAwareClassFactory(
195
hasFeatureFlag,
196
NewPaymentProcessor,
197
LegacyPaymentProcessor
198
);
199
200
container.register("PaymentProcessor", { useFactory: paymentProcessorFactory });
201
202
// Configuration-based repository selection
203
const usePostgres = (container: DependencyContainer) => {
204
const dbConfig = container.resolve<DatabaseConfig>("DatabaseConfig");
205
return dbConfig.type === "postgresql";
206
};
207
208
const userRepositoryFactory = predicateAwareClassFactory(
209
usePostgres,
210
PostgresUserRepository,
211
MongoUserRepository,
212
true // Cache for performance
213
);
214
215
container.register("UserRepository", { useFactory: userRepositoryFactory });
216
217
// A/B testing implementation selection
218
const isTestGroupA = (container: DependencyContainer) => {
219
const userId = container.resolve<string>("UserId");
220
const hash = simpleHash(userId);
221
return hash % 2 === 0; // 50/50 split
222
};
223
224
const analyticsFactory = predicateAwareClassFactory(
225
isTestGroupA,
226
EnhancedAnalytics,
227
StandardAnalytics
228
);
229
230
container.register("Analytics", { useFactory: analyticsFactory });
231
```
232
233
### Complex Factory Combinations
234
235
Examples of combining multiple factory patterns for sophisticated dependency management.
236
237
**Usage Examples:**
238
239
```typescript
240
// Cached conditional factory
241
const cachedConditionalLogger = instanceCachingFactory(
242
predicateAwareClassFactory(
243
(container) => container.resolve<string>("LogLevel") === "debug",
244
DebugLogger,
245
ProductionLogger,
246
false // Don't double-cache at predicate level
247
)
248
);
249
250
container.register("Logger", { useFactory: cachedConditionalLogger });
251
252
// Per-container cached conditional database
253
const perContainerDbFactory = instancePerContainerCachingFactory(
254
predicateAwareClassFactory(
255
(container) => {
256
try {
257
const testMode = container.resolve<boolean>("TestMode");
258
return testMode;
259
} catch {
260
return false;
261
}
262
},
263
InMemoryDatabase,
264
PostgresDatabase,
265
false // Caching handled at container level
266
)
267
);
268
269
container.register("Database", { useFactory: perContainerDbFactory });
270
271
// Multi-condition factory
272
const multiConditionFactory: FactoryFunction<NotificationService> = (container) => {
273
const env = container.resolve<string>("Environment");
274
const features = container.resolve<FeatureFlags>("FeatureFlags");
275
276
if (env === "test") {
277
return new MockNotificationService();
278
}
279
280
if (features.isEnabled("push-notifications")) {
281
return new PushNotificationService(
282
container.resolve("PushConfig")
283
);
284
}
285
286
return new EmailNotificationService(
287
container.resolve("EmailConfig")
288
);
289
};
290
291
container.register("NotificationService", {
292
useFactory: instanceCachingFactory(multiConditionFactory)
293
});
294
```
295
296
## Types
297
298
```typescript { .api }
299
// Core factory function type
300
type FactoryFunction<T> = (dependencyContainer: DependencyContainer) => T;
301
302
// Constructor type for predicate-aware factories
303
type constructor<T> = {new (...args: any[]): T};
304
305
// Predicate function type
306
type PredicateFunction = (dependencyContainer: DependencyContainer) => boolean;
307
308
// Factory wrapper function types
309
type CachingFactoryWrapper<T> = (factoryFunc: FactoryFunction<T>) => FactoryFunction<T>;
310
311
type ConditionalFactoryBuilder<T> = (
312
predicate: PredicateFunction,
313
trueConstructor: constructor<T>,
314
falseConstructor: constructor<T>,
315
useCaching?: boolean
316
) => FactoryFunction<T>;
317
```