我们在C#中有一个数据库库,我们可以这样使用:
DatabaseConnection conn = DatabaseConnection.FromConnectionString("...");
该库隐藏了不同数据库引擎之间的许多差异,如SQL函数名称,参数名称和规范等。
在内部,DatabaseConnection
类是实现一些基本方法的抽象类,但FromConnectionString
方法运行一个处理实际差异的已注册专用类型列表,并构造一个对象合适的班级。换句话说,我没有得到一个DatabaseConnection对象,我得到一个MSSQLDatabaseConnection或OracleDatabaseConnection对象,当然它继承了DatabaseConnection。
连接字符串包含有关此连接所用的数据库引擎类型和版本的信息。
我想在Python中创建一个类似的库。制作可以像这样构造的东西是正确的方法吗?
conn = DatabaseConnection("...")
或使用类方法?
conn = DatabaseConnection.FromConnectionString("...")
是第一个甚至是可能的,就是......根据传递的字符串中的数据构建这样的对象并获取其他东西,一个专门的对象?
好的,让我问一个不同的问题...... pythonic 的做法是什么?
我基本上也希望在Python中拥有DatabaseConnection基类,实现常用方法,并专注于派生类,并在某处基于连接字符串构造并返回正确类型的对象的方法或函数。
答案 0 :(得分:5)
这在Python中是可行的,但可能不是最好的方法。类工厂模式本质上是没有第一类类的语言的变通方法。由于Python确实有第一类类,因此可以将类存储在变量中,并直接使用该类创建实例。要更改创建的类,请在变量中存储不同的类。
例如:
class class1:
def greet(self):
print "hi"
class class2:
def greet(self):
print "hello"
maker = class1
obj1 = maker()
maker = class2
obj2 = maker()
obj1.greet() # prints "hi"
obj2.greet() # prints "hello"
答案 1 :(得分:3)
Python并不关心你输入的原因。
def DatabaseConnection( str ):
if ( IsOracle( str ) ):
return OracleConnection( str )
else:
return SomeOtherConnection( str )
答案 2 :(得分:1)
第一个是绝对可能的,在我看来更可取。在python中,构造函数背后真的没有很多魔力。对于所有意图和目的,它们就像任何其他功能一样。我已经多次使用这种设计模式来表明不应该直接实例化类,例如:
def DatabaseConnectionFromString(connection_string)
return _DatabaseConnection(connection_string)
def DatabaseConnectionFromSomethingElse(something_else)
connection_string = convert_something_else_into_string(something_else)
return _DatabaseConnection(connection_string)
class _DatabaseConnection(object):
def __init__(self, connection_string):
self.connection_string = connection_string
当然,这是一个人为的例子,但这应该给你一个大致的想法。
编辑:这也是继承在python中不那么令人沮丧的领域之一。你也可以这样做:
DatabaseConnection(object):
def __init__(self, connection_string):
self.connection_string = connection_string
DatabaseConnectionFromSomethingElse(object)
def __init__(self, something_else):
self.connection_string = convert_something_else_into_string(something_else)
很抱歉,这很冗长,但我想说清楚。