У нас есть библиотека базы данных на C#, которую мы можем использовать следующим образом:
DatabaseConnection conn = DatabaseConnection.FromConnectionString("...");
Эта библиотека скрывает многие различия между различными механизмами баз данных, такие как имена функций SQL, имена и спецификации параметров и т. д.
Внутренне класс DatabaseConnection является абстрактным классом, реализующим некоторые из основных методов, но метод FromConnectionString проходит через список зарегистрированных специализированных типов, который обрабатывает фактические различия и создает объект нужного класса. Другими словами, я не получаю обратно объект DatabaseConnection, вместо этого я получаю объект MSSQLDatabaseConnection или OracleDatabaseConnection, который, конечно, наследуется от DatabaseConnection.
Строка подключения содержит информацию о том, для какого типа ядра базы данных и версии это подключение.
Я хотел бы создать аналогичную библиотеку на Python. Правильный ли подход к созданию чего-то такого?
conn = DatabaseConnection("...")
или используя метод класса?
conn = DatabaseConnection.FromConnectionString("...")
возможно ли первое, то есть ... построить такой объект и получить обратно что-то еще, специализированный объект, в зависимости от данных в переданной строке?
Хорошо, позвольте мне задать другой вопрос ... Как питонический это делает?
Я в основном хочу иметь базовый класс DatabaseConnection в Python, реализующий общие методы и специализирующийся на производных классах, и где-нибудь иметь метод или функцию, основанную на конструкциях строки подключения и возвращающую правильный тип объекта.





Это возможно в 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"
Первый вариант абсолютно возможен и, на мой взгляд, предпочтительнее. В 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)
Извините, это так многословно, но я хотел прояснить это.
Спасибо, хотя и ваш, и ответы Glomeks в некотором роде отвечают на мой вопрос, мне не очень нравится переименовывать базовый класс вот так
Забавно, что вы опубликовали это, а я внес правку, не требующую названия класса. Если это не сработает, дайте мне знать, и я уверен, что смогу помочь вам еще в чем-нибудь.
Python не волнует, почему вы возвращаете тип.
def DatabaseConnection( str ):
if ( IsOracle( str ) ):
return OracleConnection( str )
else:
return SomeOtherConnection( str )
Хорошо, хм, не совсем то, что я имел в виду, но это дает мне представление о том, как реализовать «фабрику соединений по умолчанию», возможно, я воспользуюсь этой идеей, даже если она не соответствует тому, что я хотел полностью, спасибо.