Chapter 8. Python Design Patterns I

We've covered the basic building blocks of object-oriented programming. Now, we'll look at secondary structures that can be built from those blocks. These higher-level structures, called design patterns, can help organize complex systems. In the next two chapters, we'll be covering:

  • What design patterns are
  • Numerous specific patterns
  • A canonical implementation of each pattern in Python
  • Python syntax to replace certain patterns

Design patterns

When engineers and architects decide to build a bridge, or a tower, or a building, they follow certain principles to ensure structural integrity. There are various possible designs for bridges (suspension or cantilever for example), but if the engineer doesn't use one of the standard designs, and doesn't have a brilliant new design, it is likely the bridge he/she designs will collapse.

Design patterns are an attempt to bring this same formal definition for correctly designed structures to software engineering. There are many different design patterns to solve different general problems. People who create design patterns first identify a common problem faced by developers in a wide variety of situations. They then suggest what might be considered the ideal solution for that problem, in terms of object-oriented design.

We already have plenty of experience with one of the most common design patterns, the iterator. Canonically, the iterator pattern is meant to provide a common interface for looping over the items in a sequence. Separating the looping action from the sequence that is actually being looped over allows the looping code to be changed without interfering with either the code doing the looping, or the object being looped over. For example, two iterators may loop over the items in different directions, or in a sorted order. Further, it's possible to change the internal structure of an object, but still allow it to be looped over using a single iterator interface.

In typical design pattern parlance, an iterator is an object with a next() method and a done() method; the latter returns True if there are no items left in the sequence. In a programming language without built-in support for iterators, the iterator would be looped over like this:

	while not iterator.done():
		item = iterator.next()
		# do something with the item

Of course, in Python, the method is named __next__ instead, and we have the much more readable for item in iterator syntax to actually access the items. Rather than a done method, it raises StopIteration when completed. The same pattern is being applied, and it is still based on a design pattern solution, but Python has provided us with a more readable way to apply and access the pattern.

Knowing a design pattern and choosing to use it in our software does not, however, guarantee that we are creating a "correct" solution. In 1907, the Québec Bridge (to this day, the longest cantilever bridge in the world) collapsed before construction was completed because the engineers who designed it grossly underestimated the weight of the steel used to construct it. Similarly, in software development, we may incorrectly choose or apply a design pattern, and create software that "collapses" under normal operating situations or when stressed beyond its original design limits.

Any one design pattern proposes a set of objects interacting in a specific way to solve a general problem. The job of the programmer is to recognize when they are facing a specific version of that problem, and to adapt the general design in their solution.

In this chapter, we'll be reviewing several common patterns, and how they are implemented in Python. Python often provides an alternative syntax to make working with such problems simpler. We will cover both the "traditional" design, and the Python version for these patterns.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.163.175