设计模式/解决方案,用于逻辑上相似的功能,无需代码延迟

时间:2016-02-25 11:16:44

标签: python design-patterns

我正在为以下(通用)问题寻找一个优雅的解决方案。我想实现几个协议来访问文件。让我们说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中实现这一目标?

1 个答案:

答案 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)