Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
33 views

Design Patterns

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views

Design Patterns

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Design

Patterns in
Python
H. Melnyk
Agenda

1. What’s a design pattern?


2. Creational patterns
3. Structural patterns
4. Behavioral patterns
What’s a design pattern?
“Software may be
cheap to build,
but it is
incredibly
expensive to
design”
J W Reeves,

What Is Software Design?,


www.developerdotstar.co
m
What’s a design pattern?
In software engineering, a design pattern is a general reusable solution to a commonly
occurring problem within a given context in software design. A design pattern is not a
finished design that can be transformed directly into code.
Wikipedia
Design patterns are typical solutions to commonly occurring problems in software
design. They are like pre-made blueprints that you can customize to solve a recurring
design problem in your code.
You can’t just find a pattern and copy it into your program, the way you can with off-the-
shelf functions or libraries. The pattern is not a specific piece of code, but a general
concept for solving a particular problem. You can follow the pattern details and implement
a solution that suits the realities of your own program.
What’s a design pattern?
Patterns are often confused with algorithms, because both concepts describe typical
solutions to some known problems. While an algorithm always defines a clear set of
actions that can achieve some goal, a pattern is a more high-level description of a solution.
The code of the same pattern applied to two different programs may be different.
An analogy to an algorithm is a cooking recipe: both have clear steps to achieve a goal. On
the other hand, a pattern is more like a blueprint: you can see what the result and its
features are, but the exact order of implementation is up to you.
What’s a design pattern?

Benefits
Design patterns are a toolkit of tried and tested solutions to common problems in
software design. Even if you never encounter these problems, knowing patterns is still
useful because it teaches you how to solve all sorts of problems using principles of object-
oriented design.
Design patterns define a common language that you and your teammates can use to
communicate more efficiently. You can say, “Oh, just use a Singleton for that,” and
everyone will understand the idea behind your suggestion. No need to explain what a
singleton is if you know the pattern and its name.
What’s a design pattern? Criticism
✓ Kludges for a weak programming language
Usually the need for patterns arises when people choose a programming language or a
technology that lacks the necessary level of abstraction. In this case, patterns become a
kludge that gives the language much-needed super-abilities.
✓ Inefficient solutions
Patterns try to systematize approaches that are already widely used. This unification is viewed
by many as a dogma and they implement patterns “to the point”, without adapting them to
the context of their project.
✓ Unjustified use
If all you have is a hammer, everything looks like a nail.
This is the problem that haunts many novices who have just familiarized themselves with
patterns. Having learned about patterns, they try to apply them everywhere, even in situations
where simpler code would do just fine.
Classification of patterns
Design patterns differ by their complexity, level of detail and scale of applicability to the
entire system being designed.
The most basic and low-level patterns are often called idioms. They usually apply only to a
single programming language.
The most universal and high-level patterns are architectural patterns. Developers can
implement these patterns in virtually any language. Unlike other patterns, they can be
used to design the architecture of an entire application.
Classification of patterns
In addition, all patterns can be categorized by their intent, or purpose:
Creational patterns provide object creation mechanisms that increase flexibility and
reuse of existing code.
Structural patterns explain how to assemble objects and classes into larger structures,
while keeping the structures flexible and efficient.
Behavioral patterns take care of effective communication and the assignment of
responsibilities between objects.
Creational Design Patterns
Abstract Factory
Lets you produce families of related objects without specifying their concrete classes.
Usage examples: The Abstract Factory pattern is pretty common in Python code. Many
frameworks and libraries use it to provide a way to extend and customize their standard
components.
Identification: The pattern is easy to recognize by methods, which return a factory object. Then,
the factory is used for creating specific sub-components.
This example illustrates the structure of the Abstract Factory design pattern. It focuses on
answering these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Builder in Python
Builder is a creational design pattern, which allows constructing complex objects step by step.
Builder doesn’t require products to have a common interface. That makes it possible to produce
different products using the same construction process.
Usage examples: The Builder pattern is especially useful when you need to create an object
with lots of possible configuration options.
Identification: The Builder pattern can be recognized in a class, which has a single creation
method and several methods to configure the resulting object. Builder methods often support
chaining (for example, someBuilder->setValueA(1)->setValueB(2)->create()).
This example illustrates the structure of the Builder design pattern. It focuses on answering
these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Prototype in Python
Prototype is a creational design pattern that allows cloning objects, even complex ones, without
coupling to their specific classes.
All prototype classes should have a common interface that makes it possible to copy objects even if
their concrete classes are unknown. Prototype objects can produce full copies since objects of the
same class can access each other’s private fields.
Usage examples: The Prototype pattern is available in Python out of the box with a Cloneable
interface.
Identification: The prototype can be easily recognized by a clone or copy methods, etc.
This example illustrates the structure of the Prototype design pattern. It focuses on answering these
questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Singleton in Python
Singleton is a creational design pattern, which ensures that only one object of its kind exists
and provides a single point of access to it for any other code.
Singleton has almost the same pros and cons as global variables. Although they’re super-
handy, they break the modularity of your code.
You can’t just use a class that depends on Singleton in some other context. You’ll have to carry
the Singleton class as well. Most of the time, this limitation comes up during the creation of
unit tests.
Usage examples: A lot of developers consider the Singleton pattern an antipattern. That’s why
its usage is on the decline in Python code.
Identification: Singleton can be recognized by a static creation method, which returns the
same cached object.
Naïve Singleton
It’s pretty easy to implement a
sloppy Singleton. You just need
to hide the constructor and
implement a static creation
method.
The same class behaves
incorrectly in a multithreaded
environment. Multiple threads
can call the creation method
simultaneously and get several
instances of Singleton class.
Thread-safe Singleton
To fix the problem, you have to synchronize
threads during the first creation of the Singleton
object.
Structural Design Patterns
Adapter
Adapter is a structural design pattern, which allows incompatible objects to collaborate. The Adapter acts
as a wrapper between two objects. It catches calls for one object and transforms them to format and
interface recognizable by the second object.
Usage examples: The Adapter pattern is pretty common in Python code. It’s very often used in systems
based on some legacy code. In such cases, Adapters make legacy code with modern classes.
Identification: Adapter is recognizable by a constructor which takes an instance of a different
abstract/interface type. When the adapter receives a call to any of its methods, it translates parameters to
the appropriate format and then directs the call to one or several methods of the wrapped object.
This example illustrates the structure of the Adapter design pattern. It focuses on answering these
questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Adapter

This example illustrates the


structure of the Adapter design
pattern. It focuses on answering
these questions:
• What classes does it consist of?
• What roles do these classes
play?
• In what way the elements of the
pattern are related?
Bridge

Bridge is a structural design pattern that divides business logic or huge class into separate
class hierarchies that can be developed independently.
One of these hierarchies (often called the Abstraction) will get a reference to an object of
the second hierarchy (Implementation). The abstraction will be able to delegate some
(sometimes, most) of its calls to the implementations object. Since all implementations will
have a common interface, they’d be interchangeable inside the abstraction.
Usage examples: The Bridge pattern is especially useful when dealing with cross-platform
apps, supporting multiple types of database servers or working with several API providers
of a certain kind (for example, cloud platforms, social networks, etc.)
Bridge

Identification: Bridge can be recognized by a clear distinction between some controlling


entity and several different platforms that it relies on.
Conceptual Example
This example illustrates the structure of the Bridge design pattern. It focuses on answering
these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Composite

Composite is a structural design pattern that allows composing objects into a tree-like
structure and work with the it as if it was a singular object.
Composite became a pretty popular solution for the most problems that require building a
tree structure. Composite’s great feature is the ability to run methods recursively over the
whole tree structure and sum up the results.
Usage examples: The Composite pattern is pretty common in Python code. It’s often used
to represent hierarchies of user interface components or the code that works with graphs.
Identification: If you have an object tree, and each object of a tree is a part of the same
class hierarchy, this is most likely a composite. If methods of these classes delegate the
work to child objects of the tree and do it via the base class/interface of the hierarchy, this
is definitely a composite.
Composite
Conceptual Example
This example illustrates the structure of the Composite design pattern. It focuses on
answering these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Decorator
Decorator is a Conceptual pattern that allows adding new behaviors to objects dynamically by
placing them inside special wrapper objects. Using decorators you can wrap objects countless
number of times since both target objects and decorators follow the same interface. The resulting
object will get a stacking behavior of all wrappers.
Usage examples: The Decorator is pretty standard in Python code, especially in code related to
streams.
Identification: Decorator can be recognized by creation methods or constructor that accept objects
of the same class or interface as a current class.
This example illustrates the structure of the Decorator design pattern. It focuses on answering
these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Facade
Facade is a structural design pattern that provides a simplified (but limited) interface to a complex
system of classes, library or framework.
While Facade decreases the overall complexity of the application, it also helps to move unwanted
dependencies to one place.
Usage examples: The Facade pattern is commonly used in apps written in Python. It’s especially
handy when working with complex libraries and APIs.
Identification: Facade can be recognized in a class that has a simple interface, but delegates most of
the work to other classes. Usually, facades manage the full life cycle of objects they use.
This example illustrates the structure of the Facade design pattern. It focuses on answering these
questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Flyweight
Flyweight is a structural design pattern that allows programs to support vast quantities of objects by
keeping their memory consumption low.
The pattern achieves it by sharing parts of object state between multiple objects. In other words, the
Flyweight saves RAM by caching the same data used by different objects.
Usage examples: The Flyweight pattern has a single purpose: minimizing memory intake. If your
program doesn’t struggle with a shortage of RAM, then you might just ignore this pattern for a while.
Identification: Flyweight can be recognized by a creation method that returns cached objects instead
of creating new.
This example illustrates the structure of the Flyweight design pattern. It focuses on answering these
questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Proxy
Proxy is a structural design pattern that provides an object that acts as a substitute for a real service object
used by a client. A proxy receives client requests, does some work (access control, caching, etc.) and then
passes the request to a service object.
The proxy object has the same interface as a service, which makes it interchangeable with a real object
when passed to a client.
Usage examples: While the Proxy pattern isn’t a frequent guest in most Python applications, it’s still very
handy in some special cases. It’s irreplaceable when you want to add some additional behaviors to an object
of some existing class without changing the client code.
Identification: Proxies delegate all of the real work to some other object. Each proxy method should, in the
end, refer to a service object unless the proxy is a subclass of a service.
This example illustrates the structure of the Proxy design pattern. It focuses on answering these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Behavioral Design Patterns
Behavioral Design Patterns
Chain of Responsibility
Chain of Responsibility is behavioral design pattern that allows passing request along the chain
of potential handlers until one of them handles request.
The pattern allows multiple objects to handle the request without coupling sender class to the
concrete classes of the receivers. The chain can be composed dynamically at runtime with any
handler that follows a standard handler interface.
Usage examples: The Chain of Responsibility pattern isn’t a frequent guest in a Python program
since it’s only relevant when code operates with chains of objects.
Identification: The pattern is recognizable by behavioral methods of one group of objects that
indirectly call the same methods in other objects, while all the objects follow the common
interface.
This example focuses on answering these questions:
• What classes does it consist of?
• What roles do these classes play?
Command
Command is behavioral design pattern that converts requests or simple operations into objects.
The conversion allows deferred or remote execution of commands, storing command history, etc.
Usage examples: The Command pattern is pretty common in Python code. Most often it’s used as an
alternative for callbacks to parameterizing UI elements with actions. It’s also used for queueing tasks,
tracking operations history, etc.
Identification: The Command pattern is recognizable by behavioral methods in an abstract/interface type
(sender) which invokes a method in an implementation of a different abstract/interface type (receiver) which
has been encapsulated by the command implementation during its creation. Command classes are usually
limited to specific actions.
This example illustrates the structure of the Command design pattern. It focuses on answering these
questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Iterator
Iterator is a behavioral design pattern that allows sequential traversal through a complex data structure
without exposing its internal details.
Thanks to the Iterator, clients can go over elements of different collections in a similar fashion using a single
iterator interface.
Usage examples: The pattern is very common in Python code. Many frameworks and libraries use it to
provide a standard way for traversing their collections.
Identification: Iterator is easy to recognize by the navigation methods (such as next, previous and others).
Client code that uses iterators might not have direct access to the collection being traversed.
This example illustrates the structure of the Iterator design pattern. It focuses on answering these
questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Mediator
Mediator is a behavioral design pattern that reduces coupling between components of a
program by making them communicate indirectly, through a special mediator object.
The Mediator makes it easy to modify, extend and reuse individual components because they’re
no longer dependent on the dozens of other classes.
Usage examples: The most popular usage of the Mediator pattern in Python code is facilitating
communications between GUI components of an app. The synonym of the Mediator is the
Controller part of MVC pattern.
This example illustrates the structure of the Mediator design pattern. It focuses on answering
these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Memento
Memento is a behavioral design pattern that allows making snapshots of an object’s state and
restoring it in future.
The Memento doesn’t compromise the internal structure of the object it works with, as well as
data kept inside the snapshots.
Usage examples: The Memento’s principle can be achieved using the serialization, which is quite
common in Python. While it’s not the only and the most efficient way to make snapshots of an
object’s state, it still allows storing state backups while protecting the originator’s structure from
other objects.
This example illustrates the structure of the Memento design pattern. It focuses on answering
these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Observer
Observer is a behavioral design pattern that allows some objects to notify other objects about changes in
their state.
The Observer pattern provides a way to subscribe and unsubscribe to and from these events for any object
that implements a subscriber interface.
Usage examples: The Observer pattern is pretty common in Python code, especially in the GUI components.
It provides a way to react to events happening in other objects without coupling to their classes.
Identification: The pattern can be recognized by subscription methods, that store objects in a list and by
calls to the update method issued to objects in that list.
This example illustrates the structure of the Observer design pattern. It focuses on answering these
questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
State
State is a behavioral design pattern that allows an object to change the behavior when its internal state
changes.
The pattern extracts state-related behaviors into separate state classes and forces the original object to
delegate the work to an instance of these classes, instead of acting on its own.
Usage examples: The State pattern is commonly used in Python to convert massive switch-base state
machines into the objects.
Identification: State pattern can be recognized by methods that change their behavior depending on the
objects’ state, controlled externally.
This example illustrates the structure of the State design pattern. It focuses on answering these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Strategy
Strategy is a behavioral design pattern that turns a set of behaviors into objects and makes them
interchangeable inside original context object.
The original object, called context, holds a reference to a strategy object and delegates it executing the
behavior. In order to change the way the context performs its work, other objects may replace the currently
linked strategy object with another one.
Usage examples: The Strategy pattern is very common in Python code. It’s often used in various
frameworks to provide users a way to change the behavior of a class without extending it.
Identification: Strategy pattern can be recognized by a method that lets nested object do the actual work,
as well as the setter that allows replacing that object with a different one.
This example illustrates the structure of the Strategy design pattern. It focuses on answering these
questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Template Method
Template Method is a behavioral design pattern that allows you to defines a skeleton of an
algorithm in a base class and let subclasses override the steps without changing the overall
algorithm’s structure.
Usage examples: The Template Method pattern is quite common in Python frameworks.
Developers often use it to provide framework users with a simple means of extending standard
functionality using inheritance.
Identification: Template Method can be recognized by behavioral methods that already have a
“default” behavior defined by the base class.
This example illustrates the structure of the Template Method design pattern. It focuses on
answering these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Visitor

Visitor is a behavioral design pattern that allows adding new behaviors to existing class
hierarchy without altering any existing code.
Usage examples: Visitor isn’t a very common pattern because of its complexity and
narrow applicability.
This example illustrates the structure of the Visitor design pattern. It focuses on answering
these questions:
• What classes does it consist of?
• What roles do these classes play?
• In what way the elements of the pattern are related?
Thank you!

https://refactoring.guru/design-patterns

You might also like