Fabrique de classe en Python
Je suis nouveau sur Python et besoin de quelques conseils de mise en œuvre le scénario ci-dessous.
J'ai deux classes pour la gestion de vos domaines à deux bureaux d'enregistrement. Les deux ont la même interface, par exemple
class RegistrarA(Object):
def __init__(self, domain):
self.domain = domain
def lookup(self):
...
def register(self, info):
...
et
class RegistrarB(object):
def __init__(self, domain):
self.domain = domain
def lookup(self):
...
def register(self, info):
...
Je voudrais créer un Domaine de classe, étant donné qu'un nom de domaine, les charges de la bonne greffier classe basée sur l'extension, par exemple
com = Domain('test.com') #load RegistrarA
com.lookup()
biz = Domain('test.biz') #load RegistrarB
biz.lookup()
Je sais que cela peut être accompli en utilisant une fonction de fabrication (voir ci-dessous), mais est-ce la meilleure façon de le faire, ou est-il une meilleure façon de la programmation orientée objet à l'aide de fonctionnalités?
def factory(domain):
if ...:
return RegistrarA(domain)
else:
return RegistrarB(domain)
Vous devez vous connecter pour publier un commentaire.
Je pense que l'utilisation d'une fonction est fine.
La question la plus intéressante est de savoir comment déterminer le greffier à charger? Une option est d'avoir un résumé de la base de Greffier de la classe qui des implémentations concrètes sous-classe, puis effectuer une itération sur son
__subclasses__()
de l'appel d'uneis_registrar_for()
méthode de classe:Cela vous permettra de manière transparente ajouter de nouveaux
Registrar
s et délégué de la décision de domaines dont chacun prend en charge, pour eux.is_registrar_for()
sont mutuellement exclusifs, et le restera à l'avenir. L'ordre des valeurs retournées par__subclasses__()
est arbitraire. Et cet ordre, en général, les questions. Par conséquent, si quelque chose dans le code (peut-être comme mineur, comme l'ordre des définitions de classe) les modifications, vous pouvez vous retrouver avec un résultat différent. Le coût de ces bugs, OMI, est énorme, et l'emporte de loin sur les avantages de cette approche. Je voudrais aller avec l'approche de l'OP utilisé, où une seule fonction contient toute la logique de la sous-classe de la sélection.__subclasses__
renvoie seulement les sous-classes; donc multi-niveau de l'héritage aurait besoin d'un petit tweak pour être traitée correctement.__subclasses__
uniquement fonctionne pour les objets vivants. Si une classe n'est pas encore importé, il n'apparaît pas dans les résultats (car il n'a pas 'existe pas').Domain
fait cette réponse un peu déroutant.Si vous avez besoin de classes séparées pour les différents bureaux d'enregistrement (si ce n'est pas évident dans votre exemple) votre solution semble correct, bien que RegistrarA et RegistrarB probablement fonctionnalité de partage et pourrait être dérivée à partir d'une Classe De Base Abstraite.
Comme une alternative à votre
factory
fonction, vous pouvez spécifier un dict, de la cartographie de votre bureau d'enregistrement de classes:Alors:
Un bémol: Vous n'êtes pas vraiment en train de faire une Fabrique de Classe ici que vous êtes de retour instances plutôt que de classes.
En Python, vous pouvez modifier la classe:
Puis suit fonctionnera.
Je suis en utilisant cette approche avec succès.
Vous pouvez créer un "wrapper" classe et la surcharge de ses
__new__()
méthode pour retourner des instances spécialisées sous-classes, par exemple:En outre, afin de traiter les non mutuellement exclusifs conditions, une question qui a été soulevée dans d'autres réponses, la première question à se poser est de savoir si vous voulez que la classe wrapper, qui joue le rôle de répartiteur, pour régir les conditions, ou il va déléguer au cours spécialisés. Je peux suggérer partagé mécanisme, où les cours spécialisés définissent leurs propres conditions, mais l'enveloppe ne la validation, comme ceci (à condition que chaque classe spécialisée expose une méthode de classe qui permet de vérifier qu'il est un bureau d'enregistrement d'un domaine particulier, is_registrar_for(...) comme suggéré dans d'autres réponses):
__new__
retour quelque chose de différent qu'une instance decls
est mentionné, trop, et parce que le renvoiNone
est pas explicitement interdit, il conduirait à la conclusion qu'une instance d'une classe différente, qui est autorisé à être retourné.J'ai ce problème tout le temps. Si vous avez les classes intégré dans votre application (et ses modules) alors vous pouvez utiliser une fonction; mais si vous charger des plugins de manière dynamique, vous avez besoin de quelque chose de plus dynamique -- enregistrer les classes d'une usine via metaclasses automatiquement.
Ici est un modèle que je suis sûr que j'ai levé de StackOverflow à l'origine, mais je n'ai pas encore le chemin vers le post original
comment au sujet de quelque chose comme
Ici une métaclasse implicitement recueille des Registars Classes dans une ENTITÉS dict