我正在为以下(通用)问题寻找一个优雅的解决方案。我想实现几个协议来访问文件。让我们说ftp和tftp。将来可能会添加更多内容。现在我正在做:
get_file(filename):
# some generic code for opening the file etc.
if mode == 'ftp':
get_file_ftp(filename)
else:
get_file_tftp(filename)
# some generic code for closing the file etc.
get_file_ftp(filename):
# ftp-specific code
get_file_tftp(filename):
# tftp-specific code
put_file()
,ls()
和十几个功能相同。随着代码的增长,这开始变得丑陋。所以我的问题是:是否有更聪明的方法来完成工作?这是一个对这个用例有意义的设计模式吗?如果是这样,我将如何在Python中实现这一目标?
答案 0 :(得分:1)
你可以重构的两种模式是策略和装饰。
Decorator Pattern通常使用上下文管理器在Python中实现。有一个库可以让它们更容易实现,contextlib
:
from contextlib import contextmanager
@contextmanager
def get_file(filename):
# some generic code for opening the file etc.
yield
# some generic code for closing the file etc.
yield
语句可让您在with
区块中注入任何内容:
with get_file(filename) as resource:
get_file_ftp(resource)
或:
with get_file(filename) as resource:
get_file_tftp(resource)
with
块将确保执行yield
后的语句,即使存在例外情况也是如此。
实现装饰器的另一种方法是使用Python decorator syntax。我建议一个上下文管理器,因为我认为你想要在之前和之后发生任何事情。 Python的装饰器语法将使您必须自己实现异常处理。装饰器修改函数
def get_file(function):
def generic_code(filename):
... # some generic code for opening the file etc.
function(filename)
... # some generic code for closing the file etc.
return generic_code
用法:
@get_file
def get_file_ftp(filename):
... # ftp-specific code
或者,使用Strategy Pattern,您可以将处理不同文件来源的策略传递到get_file
函数中:
def get_file(filename, file_strategy):
# some generic code for opening the file etc.
file_strategy(filename)
# some generic code for closing the file etc.
然后使用它:
get_file(filename, get_file_ftp)
或:
get_file(filename, get_file_tftp)