I have a class representing a Request. I have a set of very specific requests such as "I-95", "P-22", etc. which perform distinct functions and are called by a controller class. What is the best way to do this so that one could add more requests easily down the road?
I have something like this at the 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
A Request case would be in its own separate file and look like this:
class P-22:
# Members
def __init__(self, Data):
# Set data members
def request(self):
# Submit request
And I would be able to create a request in the controller
f = Requests()
f.generate_request('RC75')
I'm striving for something that's as clean and easily extendable as possible. Thank you!
Try something like:
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
And then:
manager = RequestManager()
request = manager.generate_request('I-95')
if request is not None:
print(request.response()) # "foo"
And for registering new requests:
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"
I personally think this is better done using a Singleton-pattern for the RequestManager (untested!):
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()
This creates a statically accessible RequestManager instance:
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
and manager2
share the same requests dictionary, so updates via one of them applies to both (technically speaking to the same manager, because you retrieve the same instance twice)