Design Patterns

Design patterns are reusable solutions to common software design problems. They provide proven approaches and best practices for structuring, organizing, and implementing code. By using design patterns, developers can create flexible, maintainable, and extensible software systems that are easier to understand and evolve over time.

These patterns capture expert knowledge and experience, enabling developers to leverage established solutions to recurring design challenges.

The Gang of Four (GoF) refers to a group of four authors: Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, who wrote the book “Design Patterns: Elements of Reusable Object-Oriented Software.” This book, commonly known as the “GoF book,” is considered a seminal work in the field of software engineering. Published in 1994, it introduced 23 design patterns that have become widely adopted and recognized in the software development community.

The book emphasizes the principles of object-oriented design, such as encapsulation, inheritance, and polymorphism, and demonstrates how design patterns can be applied to achieve software designs that are flexible, maintainable, and reusable. It also discusses topics like object-oriented analysis, system architecture, and the trade-offs involved in applying different design patterns.

The GoF book has had a significant impact on software development practices and has become a cornerstone resource for understanding and applying design patterns. It has helped establish a common vocabulary and a shared understanding of design patterns among software engineers worldwide. The patterns described in the book are widely used in various programming languages and have influenced subsequent books, articles, and discussions on software design.

Categories of Design Patterns

Design patterns can be categorized into three main types:

  • Creational patterns focus on object creation mechanisms.
  • Structural patterns deal with the composition of classes and objects
  • Behavioral patterns address communication and interaction between objects.

Lets dive into detail.

Creational Design Patterns

Singleton

  • Intent: Ensures that only one instance of a class is created and provides a global point of access to it.
  • Applicability: Useful when a single instance needs to be shared throughout the system.
  • Applications: Logging Framework, Configuration Management, Database connections, Caching Objects
  • Promotes: Encapsulation, Single Responsibility Principle, Modularity
  • Possible Violation: Dependency Inversion, Coupling between singleton & dependent classes.
  • Software Attribute: Flexibility, Maintainability

Factory

  • Intent: Define an interface for creating objects, but let subclasses decide which class to instantiate.
  • Applicability: When a class can’t anticipate the type of objects it needs to create
  • Applications: GUI frameworks, plugin systems
  • Promotes: Abstraction, Encapsulation
  • Possible Violation: Dependency Inversion
  • Software Attribute: Extensibility, Reusability.

Abstract Factory

  • Intent: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
  • Applicability: When you want to create objects that are part of a specific family or group.
  • Applications: GUI toolkits, database drivers.
  • Promotes: Abstraction, Encapsulation.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Extensibility, Abstraction.

Builder

  • Intent: Separate the construction of a complex object from its representation, allowing the same construction process to create different representations.
  • Applicability: When the algorithm for creating a complex object should be independent of the parts that make up the object.
  • Applications: Document builders, HTML parsers
  • Promotes: Separation of Concerns, Encapsulation
  • Possible Violation: Dependency Inversion
  • Software Attribute: Maintainability, Flexibility.

Prototype

  • Intent: Specify the kinds of objects to create using a prototypical instance and create new objects by copying this prototype.
  • Applicability: When creating new objects by cloning existing objects is more efficient than creating them from scratch.
  • Applications: Object initialization, dynamic configurations.
  • Promotes: Flexibility, Modularity.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Reusability, Flexibility.

Structural Design Patterns

Adapter

  • Intent: Allows objects with incompatible interfaces to work together by converting the interface of one class into another interface that clients expect.
  • Applicability: When a class’s interface is incompatible with what the client expects
  • Applications: Legacy code integration, third-party library integration
  • Promotes: Compatibility, Encapsulation
  • Possible Violation: Dependency Inversion
  • Software Attribute: Interoperability, Flexibility.

Bridge

  • Intent: Decouple an abstraction from its implementation, allowing them to vary independently. It provides a way to separate the abstraction and implementation hierarchies, enabling changes in one to not affect the other.
  • Applicability: When you want to separate an abstraction from its implementation, allowing them to change independently.
  • Applications: Graphic frameworks, device drivers.
  • Promotes: Compatibility, Encapsulation
  • Possible Violation: Dependency Inversion
  • Software Attribute: Flexibility, Maintainability.

Composite

  • Intent: Represents a part-whole hierarchy of objects as a tree structure, allowing clients to treat individual objects and compositions of objects uniformly. It simplifies the handling of complex object hierarchies by providing a consistent interface.
  • Applicability: When you want to represent objects in a hierarchical structure and treat individual and composed objects uniformly.
  • Applications: GUI components, file system structures.
  • Promotes: Abstraction, Encapsulation.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Scalability, Reusability..

Decorator

  • Intent: Dynamically adds new behavior or responsibilities to an object without modifying its structure. It provides a flexible alternative to subclassing, allowing for the extension of an object’s functionality at runtime.
  • Applicability: When you need to add or modify the behavior of an object without changing its underlying class.
  • Applications: GUI components, logging functionality
  • Promotes: Open-Closed Principle, Composition over Inheritance
  • Possible Violation: Dependency Inversion
  • Software Attribute: Flexibility, Modifiability.

Facade

  • Intent: Provide a unified interface to a set of interfaces in a subsystem, simplifying their usage.
  • Applicability: When you want to provide a simplified interface to a complex subsystem.
  • Applications: APIs, complex libraries.
  • Promotes: Abstraction, Encapsulation.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Simplicity.

Flyweight

  • Intent: Shares common state between multiple objects to reduce memory usage and improve performance. It allows for the efficient sharing of intrinsic (invariant) state, while maintaining separate extrinsic (context-dependent) state for each object.
  • Applicability: When you need to support a large number of objects with limited resources.
  • Applications: Text editors, game engines.
  • Promotes: Performance optimization, Encapsulation.
  • Possible Violation: Dependency Inversion
  • Software Attribute: Efficiency, Reusability.

Proxy

  • Intent: Provide a surrogate or placeholder for another object to control access to it.
  • Applicability: When you want to add an extra level of indirection to control access to an object.
  • Applications: Remote services, lazy loading, access control
  • Promotes: Abstraction, Encapsulation
  • Possible Violation: Dependency Inversion
  • Software Attribute: Security, Extensibility.

Behavioural Design Patterns

Chain of Responsibility

  • Intent: Allows an object to pass a request along a chain of potential handlers until one of them handles the request. It decouples senders and receivers, providing flexibility in assigning responsibilities dynamically.
  • Applicability: When you want to decouple request senders from receivers and allow multiple objects to handle the request.
  • Applications: Event handling, request processing pipelines.
  • Promotes: Loose coupling, Separation of Concerns.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Modifiability, Extensibility.

Command

  • Intent: Encapsulate a request as an object, allowing you to parameterize clients with different requests, queue or log requests, and support undoable operations. It separates the sender of a request from the receiver.
  • Applicability: When you want to decouple a sender and receiver of a request, and allow for the parameterization of requests.
  • Applications: GUI actions, job queues.
  • Promotes: Encapsulation, Modularity.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Flexibility, Modularity.

Interpreter

  • Intent: Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language. It enables language or grammar parsing and interpretation, often used in implementing domain-specific languages.
  • Applicability: When you want to interpret and evaluate sentences in a language.
  • Applications: Query languages, regular expression matching.
  • Promotes: Language processing, Encapsulation.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Extensibility, Maintainability.

Iterator

  • Intent: Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
  • Applicability: When you want to access elements of a collection without exposing its internal structure.
  • Applications: Collections, database result sets.
  • Promotes: Abstraction, Encapsulation.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Flexibility, Reusability.

Mediator

  • Intent: Define an object that encapsulates how a set of objects interact, promoting loose coupling between them. It centralizes complex communication and coordination logic between objects, facilitating maintainability and extensibility.
  • Applicability: When a set of objects communicate in complex ways and need to be decoupled from each other.
  • Applications: Chat systems, event-driven architectures.
  • Promotes: Loose coupling, Separation of Concerns.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Modifiability, Maintainability.

Memento

  • Intent: Without violating encapsulation, capture and externalize an object’s internal state so that it can be restored later.
  • Applicability: When you want to capture the state of an object and restore it later without exposing its implementation details.
  • Applications: Undo/redo functionality, checkpoint systems.
  • Promotes: Encapsulation, Modularity.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: State Management, Extensibility.

Observer

  • Intent: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
  • Applicability: When a change to one object requires changing others without coupling the classes together.
  • Applications: Event-driven systems, user interfaces
  • Promotes: Loose coupling, Separation of Concerns
  • Possible Violation: Dependency Inversion
  • Software Attribute: Modifiability, Extensibility.

State

  • Intent: Allow an object to alter its behavior when its internal state changes. It encapsulates different behaviors as distinct states, promoting modularity and flexibility in handling state-specific logic.
  • Applicability: When an object’s behavior needs to change based on its internal state.
  • Applications: State machines, game characters.
  • Promotes: Encapsulation, Modularity.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Flexibility, Modularity.

Strategy

  • Intent: Define a family of algorithms, encapsulate each one, and make them interchangeable. It enables flexible selection of algorithms at runtime.
  • Applicability: When you need to dynamically change the behavior of an object at runtime.
  • Applications: Sorting algorithms, payment gateways
  • Promotes: Abstraction, Encapsulation, modularity
  • Possible Violation: Dependency Inversion
  • Software Attribute: Flexibility, Modifiability.

Template Method

  • Intent: Define the skeleton of an algorithm in a method, deferring some steps to subclasses.
  • Applicability: When you want to define a common algorithm structure but allow subclasses to implement certain steps.
  • Applications: Workflow systems, code generation.
  • Promotes: Abstraction, Encapsulation
  • Possible Violation: Dependency Inversion
  • Software Attribute: Reusability, Maintainability.

Visitor

  • Intent: Separate algorithms from the objects they operate on, allowing new operations to be added without modifying the objects. It promotes extensibility by encapsulating operations in separate visitor objects.
  • Applicability: When you want to define new operations on an object structure without modifying its classes.
  • Applications: Document processors, compilers.
  • Promotes: Separation of Concerns, Encapsulation.
  • Possible Violation: Dependency Inversion.
  • Software Attribute: Extensibility, Separation of Concerns.

References:

https://en.wikipedia.org/wiki/Design_Patterns

https://refactoring.guru/design-patterns

GoF Book:

Comments

Leave a Reply