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: 2019
Why 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 4
Explanation of the Example
Shape Classes:
Circle
andSquare
are classes representing different shapes. Each class has a constructor to initialize its properties and adraw
method to display the shape.
ShapeFactory Class:
- The
ShapeFactory
class has a static methodcreateShape
that 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
type
parameter. - If the type is ‘circle’, it returns a new
Circle
instance. If the type is ‘square’, it returns a newSquare
instance. If the type is unsupported, it throws an error.
Using the Factory:
- Two shapes,
circle
andsquare
, are created using theShapeFactory.createShape
method. - The
draw
method 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.