以两种或多种方式连接到服务,在Python中委托方法执行
我遇到了一个有趣的例子,根据消费者的偏好,我必须以两种不同的方式连接到web服务。出于这个问题的目的,我不想提及任何产品,假设它是一个称为“服务”的web服务,可以由RestAPI和MessageBroker访问 我的简化代码如下所示:以两种或多种方式连接到服务,在Python中委托方法执行,python,python-3.x,oop,object,inheritance,Python,Python 3.x,Oop,Object,Inheritance,我遇到了一个有趣的例子,根据消费者的偏好,我必须以两种不同的方式连接到web服务。出于这个问题的目的,我不想提及任何产品,假设它是一个称为“服务”的web服务,可以由RestAPI和MessageBroker访问 我的简化代码如下所示: import configparser import os from MyApp.Exceptions import WrongModeException class Service(object): cfg_file = 'path/to/cfg.
import configparser
import os
from MyApp.Exceptions import WrongModeException
class Service(object):
cfg_file = 'path/to/cfg.ini'
config = configparser.ConfigParser()
config.read(cfg_file)
@staticmethod
def generate_password():
return 'ToPsEcReTp4ssw0rD'
class ServiceAPI(Service):
def __init__(self):
self.connection = APIConnect(self.config.some_param)
def do_stuff(self, a):
self.connection.do_stuff(a=a)
class ServiceMessageBroker(Service):
def __init__(self):
self.connection = MessageBrokerConnect(self.config.some_param)
def do_stuff(self, a):
self.connection.do_stuff(a=a)
class ServiceWrapper(Service):
def __init__(self):
mode = self.config.get(option='mode')
if mode == 'Message Broker':
self.service = ServiceMessageBroker()
elif mode == 'API':
self.service = ServiceAPI()
else:
raise WrongModeException
os.sys.exit(1)
def do_stuff(self, **kwargs):
self.service.do_stuff(**kwargs)
if __name__ == '__main__':
s = ServiceWrapper()
s.do_stuff(a='blabla')
有更好更干净的方法吗?我曾考虑在字典中映射适当的函数,然后使用它来执行,但对我来说,这似乎太难看了
提前谢谢 在我看来,使用字典作为函数分派器是干净的、适应性强的。我更喜欢使用
if
/elif
/else
构造,尤其是如果它有助于可读性的话
例如,我觉得这更容易理解:
class ServiceWrapper(Service):
def __init__(self):
mode = self.config.get(option='mode')
d = {'Message Broker': ServiceMessageBroker,
'API': ServiceAPI}
if mode not in d:
raise WrongModeException
os.sys.exit(1)
self.service = d[mode]()
def do_stuff(self, **kwargs):
self.service.do_stuff(**kwargs)
你不能把包装纸变成工厂吗
def create_service():
mode = ...
service_classes = {'Message Broker': ServiceMessageBroker,
'API': ServiceAPI }
try:
service_cls = service_classes[mode]
except KeyError:
raise WrongModeException
service_obj = service_cls()
return service_obj
我的一位朋友提出了一个更具pythonic和clean的解决方案,其中还包括您的建议:
import configparser
import os
from MyApp.Exceptions import WrongModeException
class AbstractService(object):
cfg_file = 'path/to/cfg.ini'
config = configparser.ConfigParser()
config.read(cfg_file)
def do_stuff(self, a):
raise NotImplementedError
class ServiceAPI(AbstractService):
def __init__(self):
self.connection = APIConnect(self.config.some_param)
def do_stuff(self, a):
self.connection.do_stuff(a=a)
class ServiceMessageBroker(AbstractService):
def __init__(self):
self.connection = MessageBrokerConnect(self.config.some_param)
def do_stuff(self, a):
self.connection.do_stuff(a=a)
class Service(object):
def __new__(cls, *args, **kwargs):
mode = AbstractService.config.get(option='mode')
class_mapping = {
'Message Broker': ServiceMessageBroker,
'API': ServiceAPI
}
try:
chosen_class = cls.class_mapping[mode]
except KeyError:
raise WrongeModeException
return super(Service, cls).__new__(chosen_class, *args, **kwargs)
if __name__ == '__main__':
s = ServiceWrapper()
s.__init__()
s.do_stuff(a='blabla')
这绝对是一个选择。但由于其他原因,我还是希望它是一门课。谢谢然后你仍然需要显式地转发每个调用,或者做一些更复杂的事情,比如重写call方法——这不是你应该轻易做的事情。我承认,看起来更干净