5

我有一个可以与 Oracle 或 MySQL 交互的类。该类使用“Oracle”或“MySQL”关键字和一些其他数据库类型的标准参数(打印什么,是否停止异常等)进行初始化。

在我开始时根据需要添加很容易if Oracle do A, elif MySQL do B,但是随着我添加更多仅适用于一种数据库类型的专用代码,这变得很难看。我将这个类分成两部分,一类用于 Oracle,另一类用于 MySQL,并带有一些共享函数以避免重复代码。

处理调用这些新类的最 Pythonic 方式是什么?我是否创建一个使用相同关键字并返回正确类的包装函数/类?我是否将所有调用旧泛型类的代码更改为调用正确的特定于 DB 的类?

如果需要,我很乐意模拟一些示例代码,但我认为没有必要。提前感谢您的帮助!

4

2 回答 2

4

我是否创建一个使用相同关键字并返回正确类的包装函数/类?

这就是想法。这样的函数称为工厂函数:

def connect_to(db, *args):
    if db == "MySQL":
        return MySQL(*args)
    elif db == "Oracle":
        return Oracle(*args)
    else:
        raise ValueError("unknown database type: %r" % db)

确保两个数据库类具有相同的 API。您可以使用鸭子类型或抽象基类 (ABC) 来实现这一点;如果在类之间共享功能,或者如果您想isinstance检查对象是否代表数据库连接,则后者最有用。

在共享功能的情况下,模板方法模式通常会派上用场。

于 2012-10-29T16:37:29.857 回答
3

创建一个工厂类,它根据参数返回一个实现。然后,您可以为两种 DB 类型使用一个通用基类,每种都有一个实现,并让工厂根据参数创建、配置和返回正确的实现给用户。

当两个类的行为非常相似时,这很有效;但是一旦您想使用 DB 特定功能,它就会变得丑陋,因为您需要像isFeatureXSupported()(好方法)或isOracle()(更简单但不好的方法,因为它将帮助程序类中的哪个 DB 具有哪个功能的知识转移到应用程序代码中)。

或者,您可以实现两者的所有功能并在不支持时抛出异常。在您的代码中,您可以查找异常来检查这一点。这使代码更干净,但现在,您可以真正检查某个功能是否可用,而无需实际使用它。这可能会导致应用程序代码出现问题(例如,当您想要禁用菜单时,或者当应用程序可以通过其他方式执行此操作时)。

于 2012-10-29T16:11:43.650 回答