2016-06-10 13 views
1

Ich habe eine Klasse, die eine Anfrage darstellt. Ich habe eine Reihe sehr spezifischer Anfragen wie "I-95", "P-22" usw., die verschiedene Funktionen ausführen und von einer Controller-Klasse aufgerufen werden. Was ist der beste Weg, dies zu tun, so dass man problemlos weitere Anfragen hinzufügen kann?Erstellen einer Reihe von Python-Klassen

Ich habe so etwas wie dies im Moment:

class Requests: 
    def __init__(self): 
      self.types = [ 
        'I-95', 
        'P-22', 
        ... 
      ] 

    def generate_request(self,type, Data): 
      # Here I would call the appropriate case for the type, e.g. P-22 

Ein Antrag Fall in seiner eigenen separaten Datei würde und wie folgt aussehen:

class P-22: 
    # Members 
    def __init__(self, Data): 
     # Set data members 
    def request(self): 
     # Submit request 

Und ich wäre in der Lage ein zu schaffen Anforderung in der Steuerung

f = Requests() 
f.generate_request('RC75') 

Ich strebe nach etwas, das so sauber und leicht zu erweitern ist so möglich wie möglich. Vielen Dank!

+0

Was magst du an deiner gegenwärtigen Lösung nicht? – rrauenza

+0

Gut für den Anfang möchte ich etwas wie ein Enum mit der Liste der Anfragetypen implementieren. Ein Schlüsselwertpaar-Lexikon vielleicht mit dem Namen der Anfrage als Schlüssel und einem Zeiger auf seine Funktionen als Wert. – Answoquest

Antwort

8

Versuchen Sie so etwas wie:

class BaseRequest: 
    name = None 


class FooRequest(BaseRequest): 
    name = 'I-95' 

    def response(self): 
     return "foo" 


class BarRequest(BaseRequest): 
    name = 'P-22' 

    def response(self): 
     return "bar" 


class RequestManager: 

    def __init__(self): 
     self.requests = { 
      FooRequest.name: FooRequest, 
      BarRequest.name: BarRequest 
     } 

    def generate_request(self, name): 
     if name in self.requests: 
      return self.requests[name]() 

    def register_request(self, request_class): 
     assert issubclass(request_class, BaseRequest), \ 
      'Request class not a subclass of BaseRequest' 
     assert hasattr('name', request_class) and isinstance(request_class.name, str), \ 
      'Request name not correctly configured' 
     self.requests[request_class.name] = request_class 

Und dann:

manager = RequestManager() 
request = manager.generate_request('I-95') 
if request is not None: 
    print(request.response()) # "foo" 

und neue Anforderungen für die Registrierung:

class NewRequest(BaseRequest): 
    name = 'N-1' 

    def response(self): 
     return "new" 

manager = RequestManager() 
manager.register_request(NewRequest) 
request = manager.generate_request('N-1') 
if request is not None: 
    print(request.response()) # "new" 

Ich persönlich denke, das ist besser getan ist ein Singleton-pattern für die Verwendung von RequestManager (ungetestet!):

class RequestManager: 

    instance = None 

    class __RequestManager: 
     requests = { 
      FooRequest.name: FooRequest, 
      BarRequest.name: BarRequest 
     } 

     def generate_request(self, name): 
      if name in self.requests: 
       return self.requests[name]() 

     def register_request(self, request_class): 
      assert issubclass(request_class, BaseRequest), \ 
       'Request class not a subclass of BaseRequest' 
      assert hasattr('name', request_class) and isinstance(request_class.name, str), \ 
       'Request name not correctly configured' 
      self.requests[request_class.name] = request_class 

    def __new__(cls): 
     if not cls.instance: 
      cls.instance = cls.__RequestManager() 
     return cls.instance 

    @staticmethod 
    def getInstance(): 
     return RequestManager() 

Dies schafft ein statisch zugänglich RequestManager Beispiel:

manager = RequestManager.getInstance() 
# Rest same as before, register some requests, etc. 

manager2 = RequestManager.getInstance() # This is actually the same manager ie. the same instance! 

manager und manager2 Aktien der gleichen Anfragen Wörterbuch, so dass Updates über eine von ihnen gilt für beide (technisch auf den gleichen Manager zu sprechen, weil Sie abrufen die gleiche Instanz zweimal)

+0

Schöne, 10/10, 11/10 mit Reis – Answoquest

+0

Eine andere Frage: Ich möchte ein Entwickler in der Lage sein, eine eigene Falldatei zu schreiben, und fügen Sie es zu etwas wie einem Paket hinzu, das alle Falldateien enthält. Wie könnte ich das tun, ohne dass sie die neue Datei explizit zu den Importen hinzufügen müssen? Ich möchte für sie nur die Datei hinzufügen und eine neue Zeile mit dem Namen und Funktionszeiger hinzufügen – Answoquest

+1

Aktualisierte Antwort, um die Registrierung neuer Anfragen zu ermöglichen –