Design Patterns: Introduction

Design Patterns: Introduction

What is a Design Pattern

A design pattern is a reusable solution to commonly occurring problems within a given context. It is not the finished design that can be applied directly to source and machine code. Instead, it provides a description and template for how to solve the problem that can be used in many different situations. It is the best practice that programmers can use to solve common problems when designing an application.

The use of successful designs and architectures is facilitated by design patterns. The use of established principles as design techniques makes them more readily available to developers of new systems. In other words, design patterns speed up the process of getting a design right.

Design Pattern Structure

A design pattern has four essential elements.

  • Pattern Name

  • Problem

  • Solution

  • Consequence

The pattern name is a handle we use to describe the design problem, its solutions, and its consequences in a word or two. It lets us design at a higher level of abstraction. It makes it easier to think about design and to communicate them and their trade-offs to others.

The problem describes when to apply the pattern. It explains the problem and its context. Sometimes the pain will include a list of conditions that must be met before it makes sense to apply the pattern.

The solution describes the elements that make up the design, their relationships, responsibilities, and collaborations. The solution doesn't describe a particular concrete design or implementation Instead, It provides an abstract description of a design problem and how a general arrangement of elements (classes and objects in our case) solves it.

The consequences are the results and trade-offs of applying the pattern. Though consequences are often unvoiced when we describe design decisions, they are critical for evaluating design alternatives and understanding the cost and benefit of applying the pattern.

The Catalog of Design Patterns

I've listed some well-known design patterns along with brief descriptions from the GOF Design Patterns book

  • Creational Patterns

    • Factory Method - creates an interface for object creation but leaves it up to subclasses to determine which class should be instantiated.

    • Abstract Factory - offers a way to define a blueprint for producing groups of interconnected objects without requiring specific details about the actual classes of those objects.

    • Builder - decouples the assembly of a complex object from its structure, allowing the same assembly process to generate various representations.

    • Prototype - Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.

    • Singleton - guarantees that a class has just a single instance and offers a universal means to access that instance.

  • Structural Patterns

    • Adapter - transforms a class's interface into a different interface that matches the expectations of its clients.

    • Bridge - separates an abstraction from how it's implemented so that changes in one don't affect the other, allowing them to evolve independently.

    • Composite - combines individual objects into hierarchical tree structures to represent relationships between parts and wholes.

    • Decorator - dynamically adds extra responsibilities to an object.

    • Facad - offers a single, simplified interface that encompasses a group of interfaces within a subsystem.

    • Flyweight - uses sharing to support large numbers of fine-grained objects efficiently.

    • Proxy - offers a stand-in or substitute for another object, controlling and regulating access to that object.

  • Behavioral Patterns

    • Chain of Responsibility - prevents tight connections between the sender of a request and its recipient by providing multiple objects with the opportunity to handle the request.

    • Command - wraps a request as an object, allowing you to customize clients with various requests, queue or record requests, and enable reversible actions.

    • Iterator - offers a method to access the elements of a collective object sequentially while hiding the underlying structure of that object.

    • Memento - Without breaching encapsulation, record and externalize an object's internal state to enable the object's restoration to that state at a later time.

    • Observer - establishes a relationship of one-to-many between objects, ensuring that when one object undergoes a change in state, all of its dependents are automatically notified and updated.

    • State - enables an object to modify its actions or behavior in response to changes in its internal state.

    • Strategy - defines a group of algorithms, encapsulates each of them separately, and enables them to be switched out interchangeably.

    • Template Method - creates the basic structure of an algorithm within a method, delegating specific steps to subclasses for customization.

    • Visitor - represents an operation to be performed on the elements of an object structure.

Fig.1 - How to Select a Design Pattern

Conclusion

A comprehensive discussion on the use of design patterns should also include some guidance on what not to do when employing them. Design patterns are not focused on designs like straightforward data structures such as linked lists and hash tables that can be represented in classes and directly reused. Likewise, they are not intricate, application-specific designs that pertain to an entire application or subsystem.

It's important to apply a design pattern only when you genuinely require the flexibility it offers. The Consequences sections become especially valuable when assessing the advantages and drawbacks of a pattern.