Design Pattern in Software Engineering

Design Pattern in Software Engineering

Back in 1994, Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides collectively authored the groundbreaking book “Design Patterns – Elements of Reusable Object-Oriented Software,” marking the inception of the concept of design patterns in software development.

Software design patterns are like blueprints for solving common problems in software development. They provide general reusable solutions to recurring design problems, making your code more flexible, modular, and easier to understand.

Types of Design Patterns

As per the design pattern reference book Design Patterns – Elements of Reusable Object-Oriented Software, there are 23 design patterns which can be classified in three categories: Creational, Structural and Behavioral patterns.

  • Creational Patterns
  • Structural Patterns
  • Behavioural Patterns

Creational Patterns

Creational patterns deal with the process of object creation in a way that is both flexible and efficient. They provide mechanisms to create objects without specifying the exact class of the object that will be created. Examples include the Singleton pattern, Factory Method pattern, and Abstract Factory pattern.

Singleton Pattern ensures a class has only one instance and provides a global point of access to it. For example authentication class.

Factory Method Pattern defines an interface for creating an object but leaves the choice of its type to the subclasses. For example creating a single class shape, which can be then inherited to a circle, triangle etc.

Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. For example, creating a GUI toolkit that supports multiple operating systems.

Builder Pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

Prototype Pattern creates new objects by copying an existing object, known as the prototype. For example, cloning objects in a graphic design application to create duplicates.

Structural Patterns

Structural patterns focus on organizing different classes and objects to form larger structures. They help in building relationships between objects and ensuring that they work together to achieve a larger goal. Examples include the Adapter pattern, Composite pattern, and Decorator pattern.

Adapter Pattern allows the interface of an existing class to be used as another interface. For example, adapting an old system to a new API or integrating third-party libraries.

Bridge Pattern separates abstraction from implementation so that the two can vary independently. For example, connecting different database interfaces to a data access layer without tying them directly.

Composite Pattern composes objects into tree structures to represent part-whole hierarchies. For example, representing a document structure where both individual elements (characters) and composite elements (paragraphs) are treated uniformly.

Decorator Pattern attaches additional responsibilities to an object dynamically. For example, adding new features or behaviours to a core component without altering its structure.

Facade Pattern provides a simplified interface to a set of interfaces in a subsystem. For example, creating a simplified interface for a complex system to make it easier to use.

Flyweight Pattern minimizes memory usage or computational expenses by sharing as much as possible with related objects. For example, managing a large number of similar objects (e.g., characters in a text editor) efficiently.

Proxy Pattern provides a surrogate or placeholder for another object to control access to it. For example, implementing lazy loading for large objects or controlling access permissions to an object.

Behavioural Pattern

Behavioural patterns are concerned with the interaction and communication between objects. They define the patterns for how objects collaborate and operate together to accomplish tasks. Examples include the Observer pattern, Strategy pattern, and Command pattern.

Chain of Responsibility Pattern passes a request along a chain of handlers. Each handler decides either to process the request or to pass it to the next handler in the chain. For example, handling user input validation in a form where different handlers validate different aspects (e.g., length, format).

Command Pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queuing of requests, and logging of the parameters. For example, implementing a menu system where each menu item is a command that triggers a specific action.

Interpreter Pattern provides a way to evaluate language grammar or expressions. It defines the grammar for the language, as well as an interpreter that interprets the expressions. For example, creating a language interpreter for mathematical expressions.

Iterator Pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation. For example, iterating through elements in a collection without revealing the internal details of the collection.

Mediator Pattern defines an object that centralizes communication between other objects, reducing direct connections between them. For example, implementing a chat application where users communicate through a central chat mediator.

Memento Pattern captures and externalizes an object’s internal state so that the object can be restored to this state later. For example, implementing undo functionality in a text editor or graphic design application.

Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. For example, implementing event handling in a graphical user interface (GUI).

State Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class. For example, implementing a vending machine that behaves differently based on its current state (e.g., idle, dispensing, out of stock).

Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. For example, implementing various sorting algorithms (bubble sort, quicksort) that can be switched at runtime.

Template Method Pattern defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps. For example, creating a template for a report generation algorithm with specific steps that can be customized by subclasses.

Self Assessment

  • What are the Design Patterns in Software Engineering?
  • In what scenarios would you choose to implement the Singleton pattern, and what benefits does it offer in those situations?
  • How does the Decorator pattern differ from traditional subclassing, and when would you prefer to use it to extend the functionality of a class?

Leave a Reply

Your email address will not be published. Required fields are marked *