Design patterns are essential tools for building robust, maintainable, and scalable applications. Understanding and effectively utilizing design patterns can set you apart in frontend interviews. In this article, we will explore the Factory Design Pattern, a powerful pattern that promotes flexible and scalable object creation.
Factory Design Pattern
The Factory Design Pattern is a creational design pattern that provides a way to create objects without specifying the exact class of the object that will be created. It defines an interface for creating an object but allows subclasses to alter the type of objects that will be created.
class Car {
constructor(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
displayInfo() {
console.log(`Car: ${this.make} ${this.model}, Year: ${this.year}`);
}
}
class Truck {
constructor(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
displayInfo() {
console.log(`Truck: ${this.make} ${this.model}, Year: ${this.year}`);
}
}
class VehicleFactory {
static createVehicle(type, make, model, year) {
switch (type) {
case 'car':
return new Car(make, model, year);
case 'truck':
return new Truck(make, model, year);
default:
throw new Error('Vehicle type not supported.');
}
}
}
const car = VehicleFactory.createVehicle('car', 'Toyota', 'Corolla', 2020);
const truck = VehicleFactory.createVehicle('truck', 'Ford', 'F-150', 2019);
car.displayInfo(); // Output: Car: Toyota Corolla, Year: 2020
truck.displayInfo(); // Output: Truck: Ford F-150, Year: 2019Why is the Factory Pattern Important?
- Encapsulation: The Factory Pattern encapsulates the creation logic of objects, providing a single point of management for the instantiation process. This leads to cleaner and more maintainable code.
- Scalability: By centralizing the object creation process, the Factory Pattern makes it easier to scale and extend your application. Adding new types of objects requires minimal changes to the existing code.
- Flexibility: The Factory Pattern allows for the creation of different types of objects based on input parameters. This flexibility makes it easy to adapt the code to changing requirements.
- Decoupling: It decouples the client code from the actual instantiation process, making it easier to modify the object creation logic without affecting the rest of the application.
Real-Time Example: Shape Factory
class Circle {
constructor(radius) {
this.radius = radius;
}
draw() {
console.log(`Drawing a Circle with radius ${this.radius}`);
}
}
class Square {
constructor(side) {
this.side = side;
}
draw() {
console.log(`Drawing a Square with side ${this.side}`);
}
}
class ShapeFactory {
static createShape(type, size) {
switch (type) {
case 'circle':
return new Circle(size);
case 'square':
return new Square(size);
default:
throw new Error('Shape type not supported.');
}
}
}
const circle = ShapeFactory.createShape('circle', 5);
const square = ShapeFactory.createShape('square', 4);
circle.draw(); // Output: Drawing a Circle with radius 5
square.draw(); // Output: Drawing a Square with side 4Explanation of the Example
Shape Classes:
CircleandSquareare classes representing different shapes. Each class has a constructor to initialize its properties and adrawmethod to display the shape.
ShapeFactory Class:
- The
ShapeFactoryclass has a static methodcreateShapethat takes the type of shape and its size as parameters. - The method uses a switch statement to determine which shape class to instantiate based on the
typeparameter. - If the type is ‘circle’, it returns a new
Circleinstance. If the type is ‘square’, it returns a newSquareinstance. If the type is unsupported, it throws an error.
Using the Factory:
- Two shapes,
circleandsquare, are created using theShapeFactory.createShapemethod. - The
drawmethod is called on each shape to display its information.
Importance in Real-World Applications
The Factory Pattern is widely used in real-world applications for creating objects in a flexible and scalable manner. It is particularly useful in scenarios where the exact types of objects may not be known until runtime. By using the Factory Pattern, you can ensure that your code is modular, easy to extend, and less prone to errors.
