Exist Technote
[Python] Factory Method Pattern (팩토리 메서드 패턴) 본문
Factory Method란?
- GOF에서 설명하는 Factory Method는 다음과 같다.
객체를 생성하기 위해 인터페이스를 정의하지만, 어떤 객체를 생성할 지에 대한 결정권을 서브클래스로 위임한다.
- 즉, 특정 인터페이스의 구체적인 구현이 여러 개 존재하는 다양한 상황에서 사용될 수 있는 패턴.
핵심
-
ObjectFactory로 생성된 인스턴스의 동작을 눈여겨보자.
class ObjectFactory: def __init__(self): self._builders = {} def register_builder(self, key, builder): self._builders[key] = builder def create(self, key, *args, **kwargs): builder = self._builders.get(key) if not builder: raise ValueError(key) return builder(*args, **kwargs)
- register_builder 메서드로 self._builders에 key와 콜러블 객체를 매핑할 수 있으며
- create 메소드를 활용하여 key로 builder를 선택하고 인자들을 전달함으로써 객체를 생성하는 인터페이스를 보유하며, 객체를 생성할 지에 대한 결정권은 builder에게 위임되어 있다.
멋진 예제
-
music.py
class MusicServiceProvider: def __init__(self): self._builders = {} def register_builder(self, service_id, builder): self._builders[key] = builder def get(self, service_id, *args, **kwargs): builder = self._builders.get(key) if not builder: raise ValueError(key) return builder(*args, **kwargs) class MelonService: def __init__(self, consumer_key, consumer_secret): self._key = consumer_key self._secret = consumer_secret def connection(self): print(f'{self._key}와 {self._secret}로 멜론 서비스와 연결') class BugsService: def __init__(self, access_code): self._access_code = access_code def connection(self): print(f'{self._access_code}로 벅스 서비스와 연결') class LocalService: def __init__(self, location): self._location = location def connection(self): print(f'{self._location}로 로컬 서비스와 연결') class MelonServiceBuilder: def __init__(self): self._instance = None def __call__(self, melon_client_key, melon_client_secret, **_ignored): if not self._instance: consumer_key, consumer_secret = \ self.authorize(melon_client_key, melon_client_secret) self._instance = MelonService(consumer_key, consumer_secret) return self._instance def authorize(self, key, secret): return 'MELON_CONSUMER_KEY', 'MELON_CONSUMER_SECRET' class BugsServiceBuilder: def __init__(self): self._instance = None def __call__(self, bugs_client_key, bugs_client_secret, **_ignored): if not self._instance: access_code = self.authorize(bugs_client_key, bugs_client_secret) self._instance = BugsService(access_code) return self._instance def authorize(self, key, secret): return 'BUGS_ACCESS_CODE' def create_local_music_service(local_music_location, **_ignored): return LocalService(local_music_location) services = MusicServiceProvider() services.register_builder('MELON', MelonServiceBuilder()) services.register_builder('BUGS', BugsServiceBuilder()) services.register_builder('LOCAL', create_local_music_service)
-
program.py
import music config = { 'melon_client_key': 'THE_SPOTIFY_CLIENT_KEY', 'melon_client_secret': 'THE_SPOTIFY_CLIENT_SECRET', 'bugs_client_key': 'THE_BUGS_CLIENT_KEY', 'bugs_client_secret': 'THE_BUGS_CLIENT_SECRET', 'local_music_location': '/usr/data/music' } melon = music.services.get('MELON', **config) melon.connection() bugs = music.services.get('BUGS', **config) bugs.connection() local = music.services.get('LOCAL', **config) local.connection() melon2 = music.services.get('MELON', **config) print(f"melon is melon2 = {melon is melon2}") bugs2 = music.services.get("BUGS", **config) print(f"bugs is bugs2 = {bugs is bugs2}")
여담
- 잘 만들어진 디자인 패턴은 레고 부품 하나하나로 구현된 성당처럼 느껴진다. 아름다울 정도이다.
참조
'Design Pattern > Creational' 카테고리의 다른 글
[Python] Object Pool Pattern (오브젝트 풀 패턴) (0) | 2020.10.05 |
---|---|
[Python] Builder Pattern (빌더 패턴) (0) | 2020.10.04 |
[Python] Borg Pattern (보그 패턴) (0) | 2020.10.04 |
[Python] Singleton Pattern (싱글톤 패턴) (0) | 2020.09.26 |
[Python] Abstract Factory Pattern (추상 팩토리 패턴) (0) | 2020.09.26 |
Comments