Abstract Factory in Python with Generic Typing
Tags: python, programming, tutorial, architecture
Published: 2022-04-12 15:52:09

I found it difficult to find cleanly typed Python code that implemented the abstract factory creational design pattern. Therefore, this is my implementation of a typed abstract factory in Python.

The following code uses [Python](https://docs.python.org/3.8/library/typing.html) 3.8 and [Mypy](http://mypy-lang.org/) 0.91.

## Implementation

The abstract factory we are going to implement is a game factory that creates players and items. For this example, we are going to implement a Rogue player which requires an attack greater than 5 to successfully hit and a Sword item that has 10 damage.

The Unified Model Language (UML) diagram at the start of this article might be a bit scary to look at it if you’re not familiar with UML but let's start with the basics. Player is an interface (Python doesn't exactly have interfaces but you can achieve the same result using an abstract class, you’ll see an example below) that contains a single method definition. Any class that implements the Player interface must implement the attack method that matches the signature, i.e.

![Player interface attack method](https://cdn-images-1.medium.com/max/2000/1*79GyJozv1teZG_3v_KQTKQ.png)

Therefore, as shown in the UML diagram the Rogue class implements attack. If attack wasn’t implemented a TypeError would be thrown. Let’s implement Rogue and Sword:

![Rogue and Sword implementation of their corresponding interfaces.](https://cdn-images-1.medium.com/max/2000/1*XtwB4y4eRkhk5Ij-m_eELg.png)

Next, we need to create two factories for Player and Item. The factory design pattern has many benefits but my personal favourite benefit is [it separates the process of creating an object from the code that depends on the interface of the object.](https://realpython.com/factory-method-python/#introducing-factory-method) Making the code more extensible and maintainable while improving readability. A lot of articles regarding the factory design pattern use a lot of jargon but in reality it is quite simple, let me show you.

In our UML diagram both the PlayerFactory and ItemFactory implement the AbstractEntityFactory interface, specifically the *generic *createmethod.

![Generic interface method for AbstractEntityFactory](https://cdn-images-1.medium.com/max/2000/1*xNMGg0BJXA9gp-maXwEeww.png)

This method might look confusing to those who are not familiar with [generics ](https://docs.python.org/3.8/library/typing.html#generics)(especially Python developers since duck typing essentially allows everything to be *“generic”*). Generic methods allow for a single function declaration to be called with different arguments or different return types. Let me show you with an example:

![Typed generic abstract factory in Python](https://cdn-images-1.medium.com/max/2232/1*uUYzF6m8V_egpXYvXmx6Gg.png)

AbstractEntityFactory is generic because it inherits Generic[T] and method create returns T . 
ItemFactory and PlayerFactory inherit AbstractEntityFactory but look closely, it declares its generic type to be Item for ItemFactory nd Player for PlayerFactory.

Lastly, we need to create our “factory of factories”, GameFactory. GameFactory encapsulates PlayerFactory and ItemFactory without specifying their concrete classes (what the abstract factory design pattern is meant to do). It sounds more complicated than it looks:

![GameFactory — Typed abstract factory in Python](https://cdn-images-1.medium.com/max/2504/1*z_oqA-eHBlZXHuHTsqjlGw.png)

Using Mypy we validated our Python code is typed correctly 🙏.

![Mypy type checking for GameFactory implementation](https://cdn-images-1.medium.com/max/2000/1*VoFpzGxkIYvVj-OC8vUucA.png)

The code snippet directly below is an example of the GameFactory creating a Sword and a Rogue, getting the sword damage and attacking with the rogue.

![Usage example of GameFactory](https://cdn-images-1.medium.com/max/2940/1*YG1khuhkRZ3hV3_J6GsYiw.png)

That’s it! You’ve successfully implemented a typed version of the abstract factory in Python while adhering to the [SOLID design principles](https://en.wikipedia.org/wiki/SOLID).