Factory Design Pattern in Node.js
Introduction
The factory design pattern is the most used design pattern, it comes under the creation design pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created. In the Factory design pattern, we create objects without exposing the creation logic to the client. This pattern is useful when there is a need to create multiple objects of similar type or when the process of object creation is complex.
In this blog I am going to teach about factory design patterns in every simple step:
- Create an interface/abstract for the objects that will be created by the factory.
import { CredentialDetails } from "src/entity/credential.entity";
export abstract class InventoryProvider {
abstract getOrders(
credential: CredentialDetails,
page?: number
):Promise<any>
}
2. Create a factory class that implements the interface and provides methods for creating objects.
import { Provider } from "src/entity/providers.enum";
import { FoodicsProvider } from "./foodics.provider";
import { InventoryProvider } from "./inventory.class";
import { Injectable } from "@nestjs/common";
import { TastyFood } from "./tasty.provider";
@Injectable()
export class InventoryProviderFactory {
constructor(
private readonly _foodicsProvider: FoodicsProvider,
private readonly _tastyProvider : TastyFood
){}
inject(provider: Provider):InventoryProvider {
switch(provider){
case Provider.Foodics:
return this._foodicsProvider;
case Provider.Tasty:
return this._tastyProvider;
}
}
}
3. Inject the factory class into the module where the objects will be used.
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { InventoryProviderFactory } from './factory/inventory.factory';
import { FoodicsProvider } from './factory/foodics.provider';
import { TastyFood } from './factory/tasty.provider';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService,InventoryProviderFactory,FoodicsProvider,TastyFood],
})
export class AppModule {}
4. In the service or controller that requires the objects, inject the factory and use it to create the objects.
// controller.ts file
@Get('api/orders')
async getOrders() {
const query = {
provider: 'foodics',
credentialDetails: {
token: 'wj749Bajd9JSPO8746bdbsjd838djksdlABdhkdAKSIDKSdhs638483jf',
type: 'bearer'
},
page: 1
} as OrderListModel
const response = await this.appService.getOrder(query)
return response
}
//service.ts file
import { Injectable } from '@nestjs/common';
import { InventoryProviderFactory } from './factory/inventory.factory';
import { OrderListModel } from './models/order.model';
@Injectable()
export class AppService {
constructor(
private readonly _inventoryProviderFactory: InventoryProviderFactory
) {}
async getOrder(query: OrderListModel){
const injectable = this._inventoryProviderFactory.inject(query.provider)
console.log(injectable)
const response = await injectable.getOrders(query.credentialDetails, query.page)
return response;
}
}
By using the Factory Design Pattern in NestJS, you can abstract the process of object creation and provide a centralized way of creating objects in your application. This can help simplify your code and make it more maintainable.
For more information or code please visit Github: https://github.com/syedabbas110/factory-design-pattern-in-nestjs
Conclusion
The factory Method Pattern allows us to construct a new object without calling the constructor directly. Actual object instantiation is handled by the factory class and this is the prime purpose of this design pattern.