Example of Decorator Design Pattern in JavaScript

Below is the problem statement to understand the Decorator Design Pattern in JavaScript:

Imagine you are developing a web application where users can create and customize their profiles. Each user has basic information such as name, email, and profile picture, but they can also choose to add optional features such as a bio, social media links, or a profile theme. You want to implement a system that allows users to dynamically customize their profiles with these optional features while keeping the codebase clean and maintainable.

The Decorator Design Pattern is ideal for this scenario because it allows you to add optional features to individual profile objects dynamically without modifying the core profile class. This promotes code reusability, flexibility, and maintainability, as new features can be easily added or removed without affecting the existing code.

1. Component Interface (Profile):

  • This is the base component interface representing a user profile.
  • It contains basic properties such as name, email, and profile picture, along with a display() method to print profile information.
JavaScript
// Profile interface representing the base component
class Profile {
    constructor(name, email, profilePicture) {
        this.name = name;
        this.email = email;
        this.profilePicture = profilePicture;
    }

    display() {
        console.log(`Name: ${this.name}`);
        console.log(`Email: ${this.email}`);
        console.log(`Profile Picture: ${this.profilePicture}`);
    }
}

2. Concrete Component (BasicProfile):

  • BasicProfile is a concrete subclass of Profile.
  • It inherits properties and methods from the base Profile class and does not contain any additional features.
JavaScript
// Concrete component representing basic profile without any additional features
class BasicProfile extends Profile {
    constructor(name, email, profilePicture) {
        super(name, email, profilePicture);
    }
}

3. Decorator (ProfileDecorator):

  • ProfileDecorator is an abstract decorator class implementing the Profile interface.
  • It maintains a reference to the decorated Profile object and delegates method calls to it.
JavaScript
// Decorator class implementing the Profile interface
class ProfileDecorator extends Profile {
    constructor(profile) {
        super(profile.name, profile.email, profile.profilePicture);
        this.profile = profile;
    }

    display() {
        this.profile.display();
    }
}

4. Concrete Decorators (BioDecorator, SocialMediaDecorator):

  • BioDecorator and SocialMediaDecorator are concrete decorators extending ProfileDecorator.
  • They add additional features (bio, social media links) to the profile and override the display() method to include the new features.
JavaScript
// Concrete decorator adding a bio to the profile
class BioDecorator extends ProfileDecorator {
    constructor(profile, bio) {
        super(profile);
        this.bio = bio;
    }

    display() {
        super.display();
        console.log(`Bio: ${this.bio}`);
    }
}

// Concrete decorator adding social media links to the profile
class SocialMediaDecorator extends ProfileDecorator {
    constructor(profile, socialMediaLinks) {
        super(profile);
        this.socialMediaLinks = socialMediaLinks;
    }

    display() {
        super.display();
        console.log(`Social Media Links: ${this.socialMediaLinks}`);
    }
}

Complete Code for the above example:

Below is the complete code of the above problem statement:

JavaScript
// Profile interface representing the base component
class Profile {
    constructor(name, email, profilePicture) {
        this.name = name;
        this.email = email;
        this.profilePicture = profilePicture;
    }

    display() {
        console.log(`Name: ${this.name}`);
        console.log(`Email: ${this.email}`);
        console.log(`Profile Picture: ${this.profilePicture}`);
    }
}

// Concrete component representing basic profile without any additional features
class BasicProfile extends Profile {
    constructor(name, email, profilePicture) {
        super(name, email, profilePicture);
    }
}

// Decorator class implementing the Profile interface
class ProfileDecorator extends Profile {
    constructor(profile) {
        super(profile.name, profile.email, profile.profilePicture);
        this.profile = profile;
    }

    display() {
        this.profile.display();
    }
}

// Concrete decorator adding a bio to the profile
class BioDecorator extends ProfileDecorator {
    constructor(profile, bio) {
        super(profile);
        this.bio = bio;
    }

    display() {
        super.display();
        console.log(`Bio: ${this.bio}`);
    }
}

// Concrete decorator adding social media links to the profile
class SocialMediaDecorator extends ProfileDecorator {
    constructor(profile, socialMediaLinks) {
        super(profile);
        this.socialMediaLinks = socialMediaLinks;
    }

    display() {
        super.display();
        console.log(`Social Media Links: ${this.socialMediaLinks}`);
    }
}

// Usage
let basicProfile = new BasicProfile("John Doe", "john@example.com", "profile.jpg");
basicProfile.display();

let profileWithBio = new BioDecorator(basicProfile, "I'm a software engineer.");
profileWithBio.display();

let profileWithSocialMedia = new SocialMediaDecorator(basicProfile, "@johndoe");
profileWithSocialMedia.display();
Output
Name: John Doe
Email: john@example.com
Profile Picture: profile.jpg

Name: John Doe
Email: john@example.com
Profile Picture: profile.jpg
Bio: I'm a software engineer.

Name: John Doe
Email: john@example.com
Profile Picture: profile.jpg
Social Media Links: @johndoe

Decorator Design Pattern in JavaScript

The Decorator Design Pattern in JavaScript is a structural design pattern that allows behavior to be added to individual objects dynamically, without affecting the behavior of other objects from the same class. It involves creating a set of decorator classes that are used to wrap concrete components.

Important Topics for the Decorator Design Pattern in JavaScript

  • What is a Decorator Design Pattern in JavaScript?
  • Characteristics of the Decorator Pattern in JavaScript
  • Real-World Example of Decorator Design Pattern in JavaScript
  • Use Cases for the Decorator Pattern in JavaScript
  • Key Components of the Decorator Design Pattern in JavaScript
  • Example of Decorator Design Pattern in JavaScript
  • Advantages of the Decorator Design Pattern in JavaScript
  • Disadvantages of the Decorator Design Pattern in JavaScript

Similar Reads

What is a Decorator Design Pattern in JavaScript?

The Decorator Design Pattern is a structural design pattern used in software development. It allows behavior to be added to individual objects, dynamically, without affecting the behavior of other objects from the same class. This pattern is useful when you need to add functionality to objects in a flexible and reusable way....

Characteristics of the Decorator Pattern in JavaScript

This pattern promotes flexibility and extensibility in software systems by allowing developers to compose objects with different combinations of functionalities at runtime. It adheres to the open/closed principle, as new decorators can be added without modifying existing code, making it a powerful tool for building modular and customizable software components. The Decorator Pattern is commonly used in scenarios where a variety of optional features or behaviors need to be added to objects in a flexible and reusable manner, such as in text formatting, graphical user interfaces, or customization of products like coffee or ice cream....

Real-World Example of Decorator Design Pattern in JavaScript

Consider a video streaming platform where users can watch movies and TV shows. Each video content may have additional features or options available, such as subtitles, language preferences, video quality options, and audio enhancements....

Use Cases for the Decorator Pattern in JavaScript

Below are some of the use cases of Decorator Design Pattern in JavaScript:...

Key Components of the Decorator Design Pattern in JavaScript

Component Interface: This is an abstract class or interface that defines the common interface for both the concrete components and decorators. It specifies the operations that can be performed on the objects.Concrete Component: These are the basic objects or classes that implement the Component interface. They are the objects to which we want to add new behavior or responsibilities.Decorator: This is an abstract class that also implements the Component interface and has a reference to a Component object. Decorators are responsible for adding new behaviors to the wrapped Component object.Concrete Decorator: These are the concrete classes that extend the Decorator class. They add specific behaviors or responsibilities to the Component. Each Concrete Decorator can add one or more behaviors to the Component....

Example of Decorator Design Pattern in JavaScript

Below is the problem statement to understand the Decorator Design Pattern in JavaScript:...

Advantages of the Decorator Design Pattern in JavaScript

The decorator pattern is a structural design pattern that allows us to add behavior to individual objects, either statically or dynamically, without affecting the behavior of other objects from the same class. It is often used to extend the functionality of classes in a flexible and reusable way. Here are some of the advantages of the decorator pattern:...

Disadvantages of the Decorator Design Pattern in JavaScript

While the Decorator pattern offers several advantages, it also has some disadvantages and trade-offs to consider when deciding whether to use it in a particular software design. Here are some of the disadvantages of the Decorator pattern:...

Contact Us