Skip to content

Instantly share code, notes, and snippets.

@vlad-bezden
Created March 8, 2019 15:52
Show Gist options
  • Save vlad-bezden/f44ff09afc673eab59a91e518660d448 to your computer and use it in GitHub Desktop.
Save vlad-bezden/f44ff09afc673eab59a91e518660d448 to your computer and use it in GitHub Desktop.
Factory Method Design Pattern in Python and it's Implementations
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example of Factory Design Patter using ObjectFactory and ServiceProvider"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Example is based on article from https://realpython.com/factory-method-python/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each builder has required parameters, and ignores any additional parameters provided through **_ignored"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"class SpotifyService:\n",
" def __init__(self, access_code):\n",
" self._access_code = access_code\n",
"\n",
" def test_connection(self):\n",
" print(f'Accessing Spotify with {self._access_code}')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class SpotifyServiceBuilder:\n",
" def __init__(self):\n",
" self._instance = None\n",
"\n",
" def __call__(self, spotify_client_key, spotify_client_secret, **_ignored):\n",
" if not self._instance:\n",
" access_code = self.authorize(\n",
" spotify_client_key, spotify_client_secret)\n",
" self._instance = SpotifyService(access_code)\n",
" return self._instance\n",
"\n",
" def authorize(self, key, secret):\n",
" return 'SPOTIFY_ACCESS_CODE'"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"class PandoraService:\n",
" def __init__(self, consumer_key, consumer_secret):\n",
" self._key = consumer_key\n",
" self._secret = consumer_secret\n",
"\n",
" def test_connection(self):\n",
" print(f'Accessing Pandora with {self._key} and {self._secret}')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"class PandoraServiceBuilder:\n",
" def __init__(self):\n",
" self._instance = None\n",
"\n",
" def __call__(self, pandora_client_key, pandora_client_secret, **_ignored):\n",
" if not self._instance:\n",
" consumer_key, consumer_secret = self.authorize(\n",
" pandora_client_key, pandora_client_secret)\n",
" self._instance = PandoraService(consumer_key, consumer_secret)\n",
" return self._instance\n",
"\n",
" def authorize(self, key, secret):\n",
" return 'PANDORA_CONSUMER_KEY', 'PANDORA_CONSUMER_SECRET'"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"class LocalService:\n",
" def __init__(self, location):\n",
" self._location = location\n",
"\n",
" def test_connection(self):\n",
" print(f'Accessing Local music at {self._location}')"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def create_local_music_service(local_music_location, **_ignored):\n",
" return LocalService(local_music_location)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ObjectFactory"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"class ObjectFactory:\n",
" def __init__(self):\n",
" self._builders = {}\n",
"\n",
" def register_builder(self, key, builder):\n",
" self._builders[key] = builder\n",
"\n",
" def create(self, key, **kwargs):\n",
" builder = self._builders.get(key)\n",
" if not builder:\n",
" raise ValueError(key)\n",
" return builder(**kwargs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ServiceProvider"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"class MusicServiceProvider(ObjectFactory):\n",
" def get(self, service_id, **kwargs):\n",
" return self.create(service_id, **kwargs)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"services = MusicServiceProvider()\n",
"services.register_builder('SPOTIFY', SpotifyServiceBuilder())\n",
"services.register_builder('PANDORA', PandoraServiceBuilder())\n",
"services.register_builder('LOCAL', create_local_music_service)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"config = {\n",
" 'spotify_client_key': 'THE_SPOTIFY_CLIENT_KEY',\n",
" 'spotify_client_secret': 'THE_SPOTIFY_CLIENT_SECRET',\n",
" 'pandora_client_key': 'THE_PANDORA_CLIENT_KEY',\n",
" 'pandora_client_secret': 'THE_PANDORA_CLIENT_SECRET',\n",
" 'local_music_location': '/usr/data/music'\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accessing Pandora with PANDORA_CONSUMER_KEY and PANDORA_CONSUMER_SECRET\n",
"Accessing Spotify with SPOTIFY_ACCESS_CODE\n",
"Accessing Local music at /usr/data/music\n",
"id(pandora) == id(pandora2): True\n",
"id(spotify) == id(spotify2): True\n"
]
}
],
"source": [
"pandora = services.get('PANDORA', **config)\n",
"pandora.test_connection()\n",
"\n",
"spotify = services.get('SPOTIFY', **config)\n",
"spotify.test_connection()\n",
"\n",
"local = services.get('LOCAL', **config)\n",
"local.test_connection()\n",
"\n",
"pandora2 = services.get('PANDORA', **config)\n",
"print(f'id(pandora) == id(pandora2): {id(pandora) == id(pandora2)}')\n",
"\n",
"spotify2 = services.get('SPOTIFY', **config)\n",
"print(f'id(spotify) == id(spotify2): {id(spotify) == id(spotify2)}')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@tybruno
Copy link

tybruno commented Apr 23, 2021

This is awesome! Thank you for making this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment