Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Implementing the Strategy Design Pattern

00:00 Design patterns in programming are like blueprints for proven techniques that solve common problems faced by developers. The strategy pattern is an object-oriented design pattern that lets you select between a family of related algorithms.

00:13 It encapsulates each algorithm or strategy into its own object, and finally allows an object’s behavior to change dynamically during execution. Meaning you can swap strategies on the fly to adapt to changing needs.

00:27 Let’s look at one way you can use the .__call__() method to implement this pattern in Python. Open up your code editor and create the file serializing.py.

00:37 You’ll be looking at a very common challenge in programming: data serialization, taking objects in memory, and converting them to a form suitable for writing to disk or transmitting over the wire.

00:47 Depending on the use or destination of the data you serialize, you often want to be able to use different strategies. This makes it a great situation to apply the strategy pattern.

00:57 The two serialization formats you’ll use will be JSON and YAML. But first, Python does not come with YAML support out of the box. So you’ll need to install the PyYAML package with pip.

01:09 You can use the command python -m pip install pyyaml. Otherwise, you’ll get an error when you try to import the yaml library, and it’s recommended that you run this command inside of a virtual environment so you can keep your system Python neat and tidy.

01:24 I won’t be going into the details of creating virtual environments here, so if you do need a refresher, check out Python Virtual Environments: A Primer.

01:34 And I’ve already installed pyyaml, so I’ll just delete this line, and close the terminal. Time to write code: import the JSON and YAML libraries. import json, import yaml.

01:50 And the first strategy will serialize to JSON: class JSONSerializer. def __call__() with a parameter self and data. return json.dumps() data, indent=4. When called, JSONSerializer instances will call json.dumps(), passing along the data argument they receive, and json.dumps() will return a JSON-formatted string with a four-space indent for readability.

02:21 The second strategy uses YAML: class YAMLSerializer

02:27 def __call__() with the parameter self and data. return yaml.dump()

02:36 data. YAMLSerializer instances, when called, take their data argument and pass it to yaml.dump(), which returns a YAML-formatted string.

02:45 And now the class that will be the kind of wrapper around these strategies, keeping the interface consistent. Class DataSerializer. def __init__() with the parameter self and serializing_strategy.

03:02 self.serializing_strategy = serializing_strategy.

03:09 This initializer stores the starting strategy as an instance attribute, and this is where the callable serializers will live. Next, define a serialize() method. def serialize() with the parameter self and data. return self.serializing_strategy(data).

03:29 serialize() invokes the current serializing strategy, passing along the data, which will either be serialized to JSON or YAML. Once again, this might seem a little confusing, but it’ll all make sense once you see it running.

03:42 So save the file, open the REPL,

03:49 and take it for a spin: from serializing import DataSerializer, JSONSerializer, YAMLSerializer.

03:59 And define a dictionary of some dummy data. Something like this: data equals a dictionary of key-value pairs. name: "Peter Bankman", age: 34, city: "New York", job: "Exterminator".

04:21 And create a serializer by calling DataSerializer() and passing in a JSONSerializer() instance. Pay close attention and make sure you call JSONSerializer() because its instances are the callables you’re working with.

04:35 serializer equals the result of calling DataSerializer() passing in the result of calling JSONSerializer(). And give it a go. To preserve the formatting, print the result of calling serializer.serialize(), passing in data, and you see your data formatted as JSON.

04:54 What’s really cool is you can switch strategies on the fly. Now, if you wanted to use the YAMLSerializer(), you can update your serializer’s serializing_strategy attribute.

05:05 serializer.serializing_strategy equals the result of calling YAMLSerializer().

05:12 Once again, be sure to call YAMLSerializer() so you’re using an instance and not the class itself, and check out your data as YAML. print(serializer.serialize(data)).

05:26 serializer now outputs completely different formatting, but maintains the same interface: elegant and effective. Another win for object-oriented programming. As a challenge, why not see if you can extend this serializer class?

05:40 You could add support for more formats, or even implement deserialization. With what you know now, the sky’s the limit. And whenever you’re ready, I’ll be waiting for you in the summary.

Become a Member to join the conversation.