Understanding Design Patterns

Understanding Design Patterns

What Are Design Patterns?

Design patterns are time-tested, reusable solutions to frequent challenges in software design. Think of them as blueprints which can be adapted and applied to resolve specific design issues in your coding projects. These aren’t one-size-fits-all, but rather guidelines to help accelerate the development process.

Why Design Patterns Matter:

  1. Accelerate Development: Design patterns offer a toolkit of solutions, streamlining the development process by providing solutions that have already been tested in the trenches.
  2. Enhanced Team Communication: With a shared vocabulary around design patterns, team discussions become more efficient. Instead of describing in detail, saying phrases like "Let's implement a Singleton here" conveys the concept immediately.
  3. Principles of Object-Oriented Design: Beyond just problem-solving, understanding design patterns deepens your grasp on the principles of object-oriented design. This knowledge, in turn, makes you a more effective and adaptable developer.

Why Learn Design Patterns?

You might think, "I've been coding for years without knowing these patterns. Why start now?" Here's the thing: you may already be using patterns unknowingly. Being intentional about learning them offers several advantages:

  • Problem-Solving Prowess: Having a repertoire of design patterns at your disposal means you have a toolkit for tackling a diverse range of challenges.
  • Efficient Communication: When the whole team is familiar with design patterns, it simplifies dialogue. A shared understanding means less time explaining and more time doing.

Remember, even if you never use a particular pattern, the act of learning them enriches your design thinking and broadens your coding horizons.

Good Practices vs. Poor Practices with Design Patterns

“If all you have is a hammer, everything looks like a nail.”

While design patterns can be very useful, they can also be misused or overused.

Let's go through some common design patterns, their criticism, and provide Python examples.

Factory Pattern

  • Purpose: Provide an interface for creating instances of a class, with its subclasses deciding which class to instantiate.
  • Criticism: Can introduce unnecessary complexity if the creation process is straightforward and doesn't require sub-classing or configuration.
  • When to use: When you have a complex creation logic or when you want to delegate the responsibility of instantiation to child classes.
  • When not to use: When object creation is simple and straightforward.

Poor Use: Using Factory when the creation process is too simple.

class Button:
    @staticmethod
    def create_button(button_type):
        return Button()

button = Button.create_button("simple")  # Overcomplicating a simple creation.
        

Good Use: Using Factory to create UI elements that vary based on the operating system.

class Button:
    @staticmethod
    def create_button(os_type):
        if os_type == "Windows":
            return WindowsButton()
        elif os_type == "Mac":
            return MacButton()
        raise ValueError("Invalid OS type")

class WindowsButton(Button):
    def render(self):
        return "Windows-style button"

class MacButton(Button):
    def render(self):
        return "Mac-style button"

button = Button.create_button("Windows")
print(button.render())  # Outputs: Windows-style button
        

Observer Pattern

  • Purpose: An object (the subject) maintains a list of its dependents (observers) and notifies them of any state changes.
  • Criticism: Can add complexity and increase the potential for unintended side-effects due to the tight coupling between observers and the subject.
  • When to use: When you need to inform multiple objects of changes to a particular object.
  • When not to use: When there's only a single dependent or when events and updates are rare.

Poor Use: Using Observer when there's only a single dependent.

class Price:
    def __init__(self):
        self._observers = []

    def add_observer(self, observer):
        self._observers.append(observer)

    def set_price(self, price):
        self.price = price
        for observer in self._observers:
            observer.update(self)

class Display:
    def update(self, subject):
        print("New price:", subject.price)

# When you only have a single dependent, this is overkill.
price = Price()
display = Display()
price.add_observer(display)
price.set_price(100)
        

Good Use: Using Observer to update multiple displays or systems when stock prices change.

class Stock:
    def __init__(self, symbol):
        self._observers = []
        self.symbol = symbol
        self._price = 0

    def add_observer(self, observer):
        self._observers.append(observer)

    def set_price(self, price):
        self._price = price
        for observer in self._observers:
            observer.update(self)

    @property
    def price(self):
        return self._price

class StockDisplay:
    def update(self, stock):
        print(f"New price for {stock.symbol}: {stock.price}")

class AlertSystem:
    def update(self, stock):
        if stock.price > 100:
            print(f"Alert! {stock.symbol} price is very high!")

google = Stock("GOOGL")
display = StockDisplay()
alert = AlertSystem()
google.add_observer(display)
google.add_observer(alert)
google.set_price(101)  # This will notify both the display and the alert system.
        

Remember, the decision to use a design pattern should not be based on its popularity, but rather on whether it genuinely fits the problem at hand. Often, simpler code without patterns is more readable and maintainable.


?? Join Us

Stay tuned with Product Development Playbook where we share insights and knowledge from our journey in product innovation.


??Resources

  • Mastering Python Design Patterns: A guide to creating smart, efficient, and reusable software - by Kamon Ayeva (Author), Sakis Kasampalis (Author)
  • Design Patterns: Elements of Reusable Object-Oriented Software - by Erich Gamma (Author), Richard Helm (Author), Ralph Johnson (Author), John Vlissides (Author)
  • Refactoring.Guru Design Patterns

要查看或添加评论,请登录

Crea的更多文章

社区洞察

其他会员也浏览了