2016-06-10 2 views
1

У меня есть класс, представляющий запрос. У меня есть набор очень специфических запросов, таких как «I-95», «P-22» и т. Д., Которые выполняют различные функции и вызывается классом контроллера. Каков наилучший способ сделать это, чтобы можно было легко добавить больше запросов по дороге?Создание набора классов Python

У меня есть что-то вроде этого на данный момент:

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 

Запрос на случай будет в своем собственном отдельном файле и выглядеть следующим образом:

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

И я смог бы создать запрос в контроллере

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

Я стремлюсь к чему-то, что так же просто и легко расширяется возможно. Спасибо!

+0

Что вам не нравится в вашем нынешнем решении? – rrauenza

+0

Ну для начала я хотел бы реализовать что-то похожее на перечисление со списком типов запросов. Словарный ключ с ключом значений, возможно, с именем запроса в качестве ключа и указателем на его функции как его значение. – Answoquest

ответ

8

Попробуйте что-то вроде:

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 

И потом:

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

А для регистрации новых запросов:

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" 

Я лично считаю, что это лучше делать, используя Singleton-pattern для RequestManager (непроверенный!):

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

Это создает статически доступный экземпляр RequestManager:

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 и manager2 одни и те же запросы словарь, поэтому обновления через один из них относится к обоим (технически говоря, к тому же менеджеру, потому что вы извлекаете тот же пример дважды)

+0

Beautiful, 10/10, 11/10 с рисом – Answoquest

+0

Другой вопрос: я хочу, чтобы разработчик мог написать собственный файл дела и добавить его в нечто вроде пакета, содержащего все файлы case. Как я могу это сделать без необходимости явно добавлять новый файл в импорт. Я бы хотел, чтобы они только добавляли файл и добавляли новую строку с указателем имени и функции – Answoquest

+1

Обновленный ответ, позволяющий регистрировать новые запросы –

Смежные вопросы