Monday, May 29, 2023

Design Patterns

 Creational Patterns:

Singleton Pattern:

Scenario: Ensure that only one instance of a class is created throughout the application, and provide a global access point to that instance.

Example: Database connection manager, where you want to ensure there is only one connection to the database throughout the application.

Factory Pattern:

Scenario: Delegate the responsibility of object creation to a factory class, allowing subclasses to decide which class to instantiate.

Example: Abstract factory pattern for creating different types of shapes (e.g., creating instances of Circle, Square, Triangle) based on the input provided.

Prototype Pattern:

Scenario: Create new objects by cloning existing objects, avoiding the need for explicit instantiation.

Example: Prototypical object creation in JavaScript, where you clone an existing object to create a new object with the same properties and behaviors.

Builder Pattern:

Scenario: Separate the construction of complex objects from their representation, allowing the same construction process to create different representations.

Example: Building a complex document (e.g., a report) where you have different builders for constructing the header, body, and footer sections. The same construction process can create different types of reports.

Abstract Factory Pattern:

Scenario: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Example: Creating furniture objects (e.g., chair, table) in different styles (e.g., Victorian, Modern) using an abstract factory. The concrete factories create furniture objects that belong to a specific style.


Structural Patterns:

Adapter Pattern:

Scenario: Convert the interface of a class into another interface that clients expect, enabling classes with incompatible interfaces to work together.

Example: Adapting a legacy API to a new system by creating an adapter class that translates the new system's expected interface to the one provided by the legacy API.

Decorator Pattern:

Scenario: Dynamically add additional responsibilities to an object by wrapping it with a decorator class, without modifying its underlying structure.

Example: Adding features to a text editor, such as spell checking or text formatting, by creating decorator classes that wrap the base text editor class.

Proxy Pattern:

Scenario: Provide a surrogate or placeholder object to control access to another object, allowing additional actions to be performed before or after accessing the original object.

Example: Remote proxy for accessing objects over a network, where the proxy handles network communication and forwards requests to the remote object.

Composite Pattern:

Scenario: Compose objects into tree structures to represent part-whole hierarchies. Clients can treat individual objects and compositions uniformly.

Example: Representing a file system hierarchy, where files and folders are treated uniformly as components, and a folder can contain both files and subfolders.


Behavioral Patterns:

Observer Pattern:

Scenario: Establish a one-to-many dependency between objects, where changes in one object (subject) trigger updates in its dependent objects (observers).

Example: Event handling system, where multiple event listeners (observers) are registered to an event source (subject), and when an event occurs, all registered listeners are notified and updated.

Strategy Pattern:

Scenario: Define a family of algorithms, encapsulate each one, and make them interchangeable. Clients can use and switch between algorithms dynamically.

Example: Sorting algorithms, where different strategies (e.g., bubble sort, merge sort, quicksort) can be encapsulated and selected dynamically based on the specific sorting requirements.

Command Pattern:

Scenario: Encapsulate a request as an object, allowing clients to parameterize clients with queueable requests and support undoable operations.

Example: Implementing an undo/redo functionality, where commands representing user actions are encapsulated as objects, allowing the execution and reversal of those actions.

Iterator Pattern:

Scenario: Provide a way to access elements of an aggregate object sequentially without exposing its underlying representation.

Example: Iterating over elements in a collection (e.g., list, array) using an iterator object that provides methods to retrieve elements one by one, abstracting the specific structure of the collection.

Template Method Pattern:

Scenario: Define the skeleton of an algorithm in a base class, allowing subclasses to override certain steps of the algorithm without changing its structure.

Example: Defining a template for different types of reports, where a base report class defines the overall structure and common steps, while subclasses provide specific implementations for individual report sections.

State Pattern:

Scenario: Allow an object to alter its behavior when its internal state changes, by encapsulating state-specific logic into separate state objects.

Example: Implementing a vending machine, where the behavior of the machine (e.g., accepting coins, dispensing products) depends on its current state (e.g., idle, selecting product, accepting payment).

Chain of Responsibility Pattern:

Scenario: Create a chain of objects, each of which has the ability to process a request and pass it to the next object in the chain. The request is processed by the first object that can handle it.

Example: Handling requests in an application, where each handler object checks if it can process the request and either handles it or passes it to the next handler in the chain.

Interpreter Pattern:

Scenario: Define a grammar for a language and interpret sentences in the language by creating objects representing expressions in the grammar.

Example: Implementing a calculator, where mathematical expressions are parsed and evaluated using interpreter objects representing different types of expressions (e.g., addition, subtraction).

These behavioral patterns provide solutions for managing interactions and behaviors between objects in a flexible and decoupled manner, allowing for easier extensibility and maintainability of the software system.