Created
March 8, 2019 15:52
-
-
Save vlad-bezden/f44ff09afc673eab59a91e518660d448 to your computer and use it in GitHub Desktop.
Factory Method Design Pattern in Python and it's Implementations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is awesome! Thank you for making this!