Modello di fabbrica astratto in Python

Aug 17 2020

Ho letto oggi sull'Abstract Factory Pattern e ho provato a realizzare la seguente implementazione.

Ho visto molte implementazioni in internet, dove usano switchdichiarazioni, ma devo dire che non mi sono piaciute molto, dato che più fabbriche fai, mi sembra che sia molto difficile aggiungere nuovi prodotti, se necessario.

Ad ogni modo, speravo che tu gli dessi un'occhiata e mi facessi sapere le tue opinioni. Grazie in anticipo per aver dedicato del tempo a recensirlo.

Fabbriche

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()

Giocatori di calcio

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)

Giocatori di hockey ( la mia creatività si è fermata qui, quindi non ho inserito alcuna differenza tra portieri e difensori )

class HockeyPlayer:
    def play(self):
        print("I'm playing hockey!")


class HockeyGoalkeeper(HockeyPlayer):
    pass


class HockeyDefender(HockeyPlayer):
    pass

Risposte

2 AJNeufeld Aug 17 2020 at 22:24

Allo stato attuale del codice, non sono necessarie le classi Factory derivate. Non fanno nulla di diverso l'uno dall'altro, quindi possono essere gestiti tutti da una classe 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),
}

Esempio di utilizzo:

>>> player = player_factory["Hockey"].create_defender()
>>> type(player)
<class '__main__.HockeyDefender'>
>>> player.play()
I'm playing hockey!
>>>

Se c'è qualche aspetto delle fabbriche che in realtà fanno qualcosa di diverso, e quindi richiedono classi derivate separate, dovrai includerlo nella tua domanda.