Patrón de fábrica abstracto en Python
He estado leyendo hoy sobre Abstract Factory Pattern e intenté hacer la siguiente implementación.
He visto muchas implementaciones en internet, donde usan switch
sentencias, pero debo decir que no me gustó mucho, ya que entre más fábricas haces, me parece que se hace muy difícil agregar nuevos productos, si es necesario.
De todos modos, esperaba que le echaras un vistazo y me dieras tu opinión. Gracias de antemano por tomarse su tiempo para revisarlo.
Fábricas
from abc import ABC, abstractmethod
class PlayerFactory(ABC):
"""
This class is meant to be an interface
"""
@abstractmethod
def create_goalkeeper(self):
pass
@abstractmethod
def create_defender(self):
pass
class FootballPlayerFactory(PlayerFactory):
def create_goalkeeper(self):
return FootballGoalkeeper()
def create_defender(self):
return FootballDefender()
class HockeyPlayerFactory(PlayerFactory):
def create_goalkeeper(self):
return HockeyGoalkeeper()
def create_defender(self):
return HockeyDefender()
Jugadores de futbol
class FootballPlayer:
def __init__(self, uses_hands):
self.uses_hands = uses_hands
def play(self):
print("I'm playing football!")
class FootballGoalkeeper(FootballPlayer):
def __init__(self):
super(FootballGoalkeeper, self).__init__(uses_hands=True)
class FootballDefender(FootballPlayer):
def __init__(self):
super(FootballDefender, self).__init__(uses_hands=False)
Jugadores de hockey ( mi creatividad se detuvo aquí, así que no incluí ninguna diferencia entre porteros y defensores )
class HockeyPlayer:
def play(self):
print("I'm playing hockey!")
class HockeyGoalkeeper(HockeyPlayer):
pass
class HockeyDefender(HockeyPlayer):
pass
Respuestas
Tal como está su código actualmente, no necesita las clases Factory derivadas. No hacen nada diferente entre sí, por lo que todos pueden ser manejados por una clase base concreta.
class PlayerFactory:
def __init__(self, goal_keeper_class, defender_class):
self._goal_keeper_class = goal_keeper_class
self._defender_class = defender_class
def create_goalkeeper(self):
return self._goal_keeper_class()
def create_defender(self):
return self._defender_class()
player_factory = {
"Football": PlayerFactory(FootballGoalkeeper, FootballDefender),
"Hockey": PlayerFactory(HockeyGoalkeeper, HockeyDefender),
}
Ejemplo de uso:
>>> player = player_factory["Hockey"].create_defender()
>>> type(player)
<class '__main__.HockeyDefender'>
>>> player.play()
I'm playing hockey!
>>>
Si hay algún aspecto de las fábricas que realmente hace algo diferente y, por lo tanto, necesita clases derivadas separadas, deberá incluirlo en su pregunta.