Skip to main content

Why Do We Talk About Design Patterns? What Is The Basic Problem We Want To Solve?

The goal of software architechture is to minimize the human resources required to and manintain the required system functionality. - Rober C. Martin

What are Design Patterns?

Design patterns are reusable solutions to common problems that arise in software design, particularly in the context of object-oriented programming (OOP). These patterns provide a template or structure for solving certain types of problems, making it easier for developers to write maintainable and efficient code.

In the context of OOP in TypeScript, design patterns can help address challenges such as creating complex objects, managing the relationships between objects, or ensuring that objects adhere to specific behaviors.

TypeScript Course Instructor Image
TypeScript Course Instructor Image

Time To Transition From JavaScript To TypeScript

Level Up Your TypeScript And Object Oriented Programming Skills. The only complete TypeScript course on the marketplace you building TypeScript apps like a PRO.

SEE COURSE DETAILS

History of Design Patterns

The history behind design patterns can be traced back to the field of architecture, but they gained significant prominence in software engineering and development in the 1990s. Design patterns provide reusable solutions to common problems that arise in software design. They can be seen as templates for solving specific issues that can be adapted to fit various contexts.

  1. Architectural origins: The concept of design patterns was initially introduced by Christopher Alexander, an architect, in the 1970s. In his book "A Pattern Language," he discussed how certain patterns could be identified and applied to solve recurring design problems in architecture.

  2. Emergence in software development: The idea was later adopted and adapted for software engineering by a group of computer scientists often referred to as the "Gang of Four" (GoF). In their seminal book "Design Patterns: Elements of Reusable Object-Oriented Software" (1994), Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides presented 23 design patterns for object-oriented programming. This book became a landmark in the field and popularized the concept of design patterns in software development.

Image of Gang Of Four

Why We Use Design Patterns?

We use design patterns for several reasons:

Reusability

Design patterns provide tried-and-tested solutions to common problems, reducing the time and effort needed to solve them from scratch. They promote reusability and modularity in software systems.

Improved communication

Design patterns provide a shared vocabulary and understanding among developers, enabling more efficient communication about design decisions and solutions.

Best practices

Design patterns encapsulate the best practices of experienced software developers, allowing novices to learn from their expertise.

Maintainability

Implementing design patterns often results in more maintainable code, making it easier to update, debug, and extend in the future.

Easier problem-solving

Design patterns provide a structured approach to problem-solving, which can help developers break down complex problems into smaller, more manageable components.

Cautions and Considerations

It's important to note that design patterns should be used wisely and not treated as a one-size-fits-all solution. They should be applied when they fit the problem context, and developers should always consider the trade-offs and potential consequences of their use.

The statement emphasizes the importance of using design patterns judiciously and being aware of their limitations. Design patterns provide reusable solutions to common problems, but they might not always be the best fit for a specific problem or context. Applying a design pattern without considering the implications can lead to unintended consequences or suboptimal solutions. Here are some reasons for this statement:

Contextual differences

Design patterns are created to address specific problems under certain conditions. A pattern that works well in one context might not be suitable for another, and blindly applying it can result in a poor design. For example, the Singleton pattern is useful when you need to ensure that only one instance of a class is created, but using it in a situation where multiple instances are actually needed would lead to problems.

Over-engineering

Sometimes, developers might be tempted to use design patterns even when a simpler solution would suffice. This can result in over-engineering, making the code more complex and harder to maintain. For example, using the Factory pattern for object creation might not be necessary if the objects are simple and don't require complex instantiation logic.

Performance implications

Design patterns can introduce additional layers of abstraction or indirection, which can have performance implications. Developers should carefully consider whether the benefits of using a pattern outweigh any potential performance trade-offs. For instance, the Decorator pattern allows for extending the functionality of an object without modifying its structure, but it can also introduce additional overhead due to the extra layer of object wrapping.

Evolving requirements

Sometimes, design patterns may not accommodate evolving requirements or future changes in the system. As projects grow and requirements change, design patterns that initially seemed like a good fit may no longer be appropriate. For example, the Observer pattern allows for a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. However, if the system later requires more sophisticated event handling or filtering, the Observer pattern might not be the best solution.

Real-world Example 🌎

Consider an e-commerce application where the payment processing logic needs to be updated to handle multiple payment methods. A developer might decide to implement the Strategy pattern to allow for easy addition of new payment methods. This pattern enables the encapsulation of payment processing algorithms within separate classes and makes it easy to switch between them at runtime. While the Strategy pattern is a good choice in this case, it's crucial to understand the problem context and requirements before deciding to use it. In another scenario, if the application only ever needs to support a single payment method, the Strategy pattern might introduce unnecessary complexity.

Here is a high-level overview of an e-commerce application's payment processing using the Strategy pattern in a class diagram. Please note that this representation might not include all the details of a real-world implementation.

In this diagram, we have a ShoppingCart class representing a shopping cart in an e-commerce application. This class has two methods: calculateTotal() to calculate the total cost of the items in the cart, and checkout(PaymentStrategy) to complete the payment process using a chosen payment strategy.

We also have an interface called PaymentStrategy, which represents the general payment strategy with a single method, pay(amount: Number). This interface is implemented by three concrete classes: CreditCardPaymentStrategy, PayPalPaymentStrategy, and BankTransferPaymentStrategy. Each of these classes provides a specific implementation of the pay() method to process payments using their respective payment methods.

The ShoppingCart class has a relationship with the PaymentStrategy interface, indicating that it uses a payment strategy to process payments during the checkout process. When the checkout() method is called, it takes an instance of a class implementing the PaymentStrategy interface as a parameter, allowing the shopping cart to use different payment methods without changing its own code.

Remember that this is a simplified example and may not cover all the nuances and complexities of a real-world e-commerce application's payment processing system.

It's essential for developers to carefully analyze the problem at hand and evaluate the suitability of a design pattern before applying it. Design patterns should be seen as tools to aid in problem-solving, rather than a one-size-fits-all solution.

What Can You Do Next 🙏😊

If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for software developers.

YouTube @cloudaffle