A Brief intro on Design Patterns

January 26, 2025

Design patterns are proven, reusable solutions to common problems in software design. They are like blueprints that guide developers in solving recurring challenges while maintaining code quality, scalability, and flexibility.

Originally formalized in the book "Design Patterns: Elements of Reusable Object-Oriented Software" by the Gang of Four (GoF), these patterns describe how classes and objects interact to solve specific problems in a way that can be reused across various projects.

How are Design Patterns Used??

1. Understanding the Problem Context :

Developers identify a problem that fits a typical scenario, like object creation, communication between components, or managing relationships between entities.

2. Selecting an Appropriate Pattern :

A relevant design pattern is chosen based on the problem.

3. Implementing the Pattern :

The pattern is implemented in the project's codebase, either directly as per the GoF structure or customized to fit the application's needs.

4. Benefits of Using Patterns :

Code Reusability: Patterns promote standardized, reusable solutions.

Maintainability: Code structured with patterns is easier to understand and modify.

Scalability: Patterns facilitate extending functionality with minimal changes.

Communication: Patterns create a shared vocabulary for developers.

a) Creational Patterns

Focus on object creation mechanisms.

Blog image

1. Singleton

Use Cases: Logging, configuration management, database connections, thread pools.

2. Factory Method

Use Cases: Creating objects without exposing instantiation logic. E.g., document editors creating different types of documents (Word, PDF).

3. Abstract Factory

Use Cases: Cross-platform UI components (buttons, menus), product families (car parts: engine, tires).

4. Builder

Use Cases: Constructing complex objects step-by-step like a house, HTML documents, or query builders.

5. Prototype

Use Cases: Copying objects where creation is expensive. E.g., cloning game objects, graphical editors.

b) Structural Patterns

Blog image

Deal with the composition of classes and objects.

1. Adapter

Use Cases: Integrating incompatible interfaces, e.g., connecting legacy systems to new APIs.

2. Bridge

Use Cases: Decoupling abstraction from implementation. E.g., different drawing APIs for 2D and 3D shapes.

3. Composite

Use Cases: Representing tree-like structures like file systems, organization hierarchies.

4. Decorator

Use Cases: Adding behavior dynamically to objects. E.g., UI components (scrollbars, borders).

5. Facade

Use Cases: Simplifying complex subsystems. E.g., unified interface for database operations.

6. Flyweight

Use Cases: Memory optimization for objects with shared states. E.g., character rendering in text editors.

7. Proxy

Use Cases: Controlling access to resources. E.g., lazy loading, virtual proxies, remote proxies.

c) Behavioral Patterns

Blog image

Focus on interaction and responsibility between objects.

1. Chain of Responsibility

Use Cases: Logging frameworks, handling requests in web servers, UI event handling.

2. Command

Use Cases: Undo/redo systems, task scheduling, remote controls.

3. Interpreter

Use Cases: Parsing languages, expressions in calculators, database queries (SQL).

4. Iterator

Use Cases: Iterating over collections like lists, trees, or graphs.

5. Mediator

Use Cases: Chat applications, reducing coupling between GUI components.

6. Memento

Use Cases: Saving state in games, undo functionality in text editors.

7. Observer

Use Cases: Event listeners in GUIs, publish-subscribe systems, stock price monitoring.

8. State

Use Cases: Managing state-dependent behavior, e.g., vending machines, media players.

9. Strategy

Use Cases: Switching algorithms at runtime, e.g., sorting algorithms, payment methods.

10. Template Method

Use Cases: Frameworks with common workflows, e.g., data parsing and validation.

11. Visitor

Use Cases: Adding operations to object structures without changing them. E.g., traversing trees, syntax analysis.