Open In App

Behavioral Design Pattern | JavaScript Design Pattern

Last Updated : 30 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Behavioral design patterns are a subset of design patterns in software engineering that deal with the interaction and responsibilities of objects. These patterns focus on how objects communicate and work together to achieve common tasks.

Uses Cases of the Behavioral Design Pattern

  • Observer Pattern: This pattern is useful when you need to maintain a one-to-many dependency between objects. For example, it is used in event handling systems, where one object notifies several other objects about any state changes.
  • Strategy Pattern: This pattern is used when you want to define a family of algorithms, encapsulate each one of them, and make them interchangeable. This allows the algorithm to vary independently from the clients that use it, making it useful when you have different variations of an algorithm that you want to use interchangeably.
  • Chain of Responsibility Pattern: This pattern is employed when you want to pass a request along a chain of handlers. It allows more than one object to handle the request, and the handler is determined dynamically at runtime. This is often used in GUI systems for handling events.
  • Command Pattern: This pattern is useful when you want to encapsulate a request as an object, thereby allowing you to parameterize clients with queues, requests, and operations. It’s commonly used in the implementation of menu systems, where menu items are bound to specific actions.
  • State Pattern: This pattern is helpful when an object changes its behavior based on its internal state. It allows an object to alter its behavior when its internal state changes. This pattern is commonly used in vending machines where a machine changes its behavior based on the current state (e.g., if it’s out of stock).
  • Iterator Pattern: This pattern is used to provide a way to access elements of an aggregate object sequentially without exposing its underlying representation. It is commonly used in collection classes, providing a way to access elements of a collection without needing to know its internal structure.
  • Interpreter Pattern: This pattern is useful when you need to define a representation for a grammar along with an interpreter to interpret the grammar. It’s commonly used in the development of programming languages and symbol-processing engines.

Example of the Behavioral Design Pattern in JavaScript Design Pattern:

Problem Statement:

We can take the example of news design here news notification system that allows news agencies to notify multiple news readers about the latest news updates. The system should provide flexibility and maintainability for future extensions and should utilize the Observer behavioral design pattern to handle the interactions between news agencies and news readers.

Below is the implementation of the above example:

Javascript




// Subject
class NewsAgency {
  constructor() {
    this.observers = [];
    this.news = null;
  }
 
  registerObserver(observer) {
    this.observers.push(observer);
  }
 
  removeObserver(observer) {
    this.observers = this.observers.filter(o => o !== observer);
  }
 
  setNews(news) {
    this.news = news;
    this.notifyObservers();
  }
 
  notifyObservers() {
    this.observers.forEach(observer => observer.update(this.news));
  }
}
 
// Observer
class NewsReader {
  constructor(name) {
    this.name = name;
  }
 
  update(news) {
    console.log(`${this.name} received news: ${news}`);
  }
}
 
// Usage
const agency = new NewsAgency();
const reader1 = new NewsReader("Reader 1");
const reader2 = new NewsReader("Reader 2");
 
agency.registerObserver(reader1);
agency.registerObserver(reader2);
 
agency.setNews("Breaking news: Behavioral Design Patterns in JavaScript!");


Output

Reader 1 received news: Breaking news: Behavioral Design Patterns in JavaScript!
Reader 2 received news: Breaking news: Behavioral Design Patterns in JavaScript!




Key Component of Behavioral Design Pattern

These are the following components of behavioral design patterns:

  • Subject: Represents the main object of interest. It maintains a list of observers and notifies them when its state changes.
  • Observer: Observers are interested in the state changes of the subject and are notified when the subject’s state changes.
  • ConcreteSubject: Implements the Subject interface and stores the state of interest. It sends notifications to its observers when its state changes.
  • ConcreteObserver: Implements the Observer interface. It registers with ConcreteSubject to receive notifications and updates its state accordingly.

Step-by-step Code Explanation for the above Example

NewsAgency Class:

Javascript




class NewsAgency {
  constructor() {
    this.observers = [];
    this.news = null;
  }


The NewsAgency class is the subject in the Observer pattern.It has a constructor that initializes an empty array observers to store registered observers and news to store the latest news update.

Register Observer Method:

Javascript




registerObserver(observer) {
    this.observers.push(observer);
  }


The registerObserver method allows news agencies to register news readers as observers. It adds the provided observer to the list of observers.

Remove Observer Method:

Javascript




removeObserver(observer) {
   this.observers = this.observers.filter(o => o !== observer);
 }


The removeObserver method enables news agencies to unregister observers. It removes the provided observer from the list of observers.

SetNews Method:

Javascript




setNews(news) {
   this.news = news;
   this.notifyObservers();
 }


The setNews method allows news agencies to set the latest news content. It updates the news property and then calls the notifyObservers method to notify all registered observers.

Notify Observer Method:

Javascript




notifyObservers() {
    this.observers.forEach(observer => observer.update(this.news));
  }


The notifyObservers method iterates through the list of observers and calls the update method of each observer, passing the latest news as a parameter.

NewsReader Class:

Javascript




class NewsReader {
  constructor(name) {
    this.name = name;
  }


The NewsReader class represents news readers, which are the observers in the Observer pattern.It has a constructor that accepts a name parameter to set the name of the news reader.

Update Method:

Javascript




update(news) {
    console.log(`${this.name} received news: ${news}`);
  }


The update method is called by the NewsAgency when news updates are available. It logs a message to the console, indicating that the news reader with the specified name has received the news.

Usage:

Javascript




const agency = new NewsAgency();
const reader1 = new NewsReader("Reader 1");
const reader2 = new NewsReader("Reader 2");
 
agency.registerObserver(reader1);
agency.registerObserver(reader2);
 
agency.setNews("Breaking news: Behavioral Design Patterns in JavaScript!");


In the usage section, we create instances of the NewsAgency and two NewsReader objects.We register reader1 and reader2 as observers with the agency using the registerObserver method..

Diagrammatical Explanation of the above Example

Screenshot-from-2023-10-14-15-40-09

Diagrammatical Representation of the given Example

Lets understand the example:

  • Subject – NewsAgency: The “NewsAgency” class represents the subject. It has the responsibility of maintaining a list of observers and notifying them of any changes. It has methods such as “registerObserver”, “removeObserver”, “setNews”, and “notifyObservers”. When “setNews” is called, it sets the news and then notifies all the registered observers by calling their “update” method.
  • Observer – NewsReader: The “NewsReader” class represents the observer. It has a “name” property and an “update” method. The “update” method is called by the “NewsAgency” when it notifies the observers, and it simply logs a message to the console with the news that was received.
  • Usage: In the usage section, a “NewsAgency” instance is created as “agency”, and two “NewsReader” instances are created as “reader1” and “reader2”. The two readers are then registered as observers with the “agency”. After that, the “agency” sets the news by calling the “setNews” method with the news as an argument. This triggers the “update” method of both “reader1” and “reader2” with the provided news, and they log the news to the console.

Advantages of the Behavioral Design Pattern

  • Loose Coupling: Behavioral design patterns promote loose coupling between objects, making it easier to change, add, or remove behaviors without affecting the entire system.
  • Reusability: By separating concerns and responsibilities, you can reuse the same behavioral patterns in various parts of your application.
  • Improved Maintainability: Behavioral patterns help to maintain a cleaner and more structured codebase, making it easier to understand and update.
  • Encapsulating algorithms: Behavioral patterns help encapsulate complex algorithm implementations, making them more manageable and easier to modify or extend.
  • Facilitating testing and debugging: With well-defined interactions between objects, testing and debugging become more straightforward.

Disadvantages of the Behavioral Design Pattern

  • Complexity: Overusing behavioral design patterns can lead to increased complexity in your code, making it harder to understand and debug.
  • Runtime Overhead: Some behavioral patterns might introduce additional runtime overhead due to the indirection in communication between objects.
  • Maintenance challenges: While behavioral patterns promote code flexibility, they can also make the codebase harder to maintain, especially if the application evolves and more patterns are introduced.
  • Overengineering risk: Applying design patterns when unnecessary can result in overengineering, leading to unnecessary complexity and reduced performance.

Conclusion

Behavioral design patterns are essential for structuring the interactions between objects in your software. They provide a foundation for creating flexible and maintainable code. When choosing a behavioral pattern, consider the specific requirements of your system and choose the pattern that best fits the problem at hand. Use these patterns judiciously, as excessive use can lead to unnecessary complexity.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads