The Prototype Design Pattern in JavaScript is a creational pattern that allows you to create new objects by cloning an existing object (the "prototype") instead of creating them from scratch, which serves as a prototype. This pattern is particularly well-suited to JavaScript, as JavaScript itself is a prototype-based language and is useful when object creation is costly or when you want to create an object that shares certain properties with a base prototype.
ES6 classes make it easier to understand the structure of objects. Using extends simplifies inheritance but before ES6, prototype
was used to inherit and implement this. Here is blog to understand this concept.
Ps : In the Prototype Design Pattern in JavaScript, there is no built-in clone() method like there is in some other languages (e.g., Java). However, you can manually implement a clone() method in your prototype or constructor function to provide similar functionality.
The idea behind the Prototype pattern is to:
- Create an object that acts as a prototype (blueprint).
- Use that object to create new instances, either by copying it or linking new instances to the prototype.
Key Concepts of Prototype Pattern
Prototype: A template object from which new objects are created.
Cloning: New objects are created by copying the prototype.
Prototype Chain: Objects can delegate behaviour to their prototype
Part 1: The Base Shape Class
class Shape {
constructor(type = 'Generic Shape', color = 'White') {
this.type = type;
this.color = color;
}
getDetails() {
return `Type: ${this.type}, Color: ${this.color}`;
}
// Clone method to create a new object with the same prototype
clone() {
return Object.create(this); // Creates a new object that inherits from this prototype
}
}
Explanation:
Purpose: The Shape class acts as a base class or "prototype" from which specific shapes like circles or rectangles can inherit.
clone()
Method: This is a key part of the Prototype Pattern. Instead of creating a new instance of a class from scratch, we create a clone of the existing instance (or "prototype"). In this case, Object.create(this) creates a new object that shares the same prototype as the original Shape.
Part 2: The Circle Class
class Circle extends Shape {
constructor(radius = 0, color = 'White') {
super('Circle', color); // Calls the parent (Shape) constructor
this.radius = radius;
}
getArea() {
return Math.PI * this.radius * this.radius;
}
}
Explanation:
Purpose: The Circle class extends the Shape class and represents a specific type of shape.
Attributes:
-
radius
: The radius of the circle. - In the constructor, the super() function calls the constructor of the Shape class, passing "Circle" as the shape type and the color.
getArea() Method: This calculates the area of the circle using the formula π * radius^2.
Part 3: The Rectangle Class
class Rectangle extends Shape {
constructor(width = 0, height = 0, color = 'White') {
super('Rectangle', color); // Calls the parent (Shape) constructor
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
Explanation:
Purpose: The Rectangle class extends the Shape class and represents another specific type of shape (a rectangle).
- Like the Circle class, the Rectangle class uses super() to call the parent class Shape constructor, specifying that this is a "Rectangle".
- getArea() Method: This calculates the area of the rectangle using the formula width * height
Part 4: Cloning and Using the Prototype
const circlePrototype = new Circle(); // Create prototype
const myCircle = circlePrototype.clone(); // Clone the prototype
myCircle.radius = 5;
myCircle.color = 'Red';
const rectanglePrototype = new Rectangle(); // Create prototype
const myRectangle = rectanglePrototype.clone(); // Clone the prototype
myRectangle.width = 10;
myRectangle.height = 5;
myRectangle.color = 'Blue';
Explanation:
Here, instead of creating myCircle and myRectangle objects from scratch using the new keyword, we are cloning prototypes.
Cloning Process:
- First, we create prototype instances (circlePrototype and rectanglePrototype).
- Then, we clone these prototypes using the clone() method, which creates new objects that inherit from the prototype object.
Modifying Cloned Instances:
- After cloning, we modify the properties (e.g., radius, width, height, color) of the cloned objects (myCircle and myRectangle) to match our needs.
- This allows us to easily create multiple objects from a base prototype, modifying only the necessary properties.
Part 5: Output
console.log(myCircle.getDetails()); // Output: Type: Circle, Color: Red
console.log(`Circle Area: ${myCircle.getArea()}`); // Output: Circle Area: 78.54
console.log(myRectangle.getDetails()); // Output: Type: Rectangle, Color: Blue
console.log(`Rectangle Area: ${myRectangle.getArea()}`); // Output: Rectangle Area: 50
Explanation:
- We use the getDetails() method inherited from the Shape class to print the details (type and color) of myCircle and myRectangle.
- We also use the getArea() methods (specific to the Circle and Rectangle classes) to calculate and display the area of each shape.
Prototype Design Pattern Perspective:
- Prototype Creation: Instead of creating new objects of Circle and Rectangle from scratch, we first create a prototype instance (circlePrototype and rectanglePrototype).
- Cloning: Once the prototype exists, the clone() method is used to create new objects based on the prototype. This is the essence of the Prototype Pattern: creating objects by copying an existing object (the prototype).
Use case:
The Prototype pattern is useful when:
- You need to create new objects by cloning existing objects.
- You want to avoid subclassing and directly reuse existing objects as blueprints.
- creation is costly or complex and when many similar objects need to be created. By using prototypes, you can streamline the process and improve efficiency.
If you've made it this far 💕✨, drop a comment below with any questions or thoughts. I'd love to hear from you and engage in some great discussions!✨
Top comments (0)