Вопрос
Я не могу понять правильные концепции фабрики.
Может ли кто-нибудь помочь мне написать простой тест? Я читаю некоторые тексты через Интернет и не могу кодировать его таким же образом. На самом деле я не могу понять процесс. Копировать код легко, но мне нужно узнать, почему это не сработает.
class Factory:
def __init__(self):
self.msg = "teste"
def fabricateAnotherObject(self,obj,**kwargs):
return apply(obj,**kwargs)
class testClass:
def __init__(self,nome,salario,endereco):
self.nome = nome
self.salario = salario
self.endereco = endereco
def __str__(self):
return "Nome: " + str(self.nome) + "\nEndereco: " + str(self.endereco) + "\nSalario: " + str(self.salario)
a = Factory()
emp = a.fabricateAnotherObject(testClass,"George",2000,"Three Four Five Avenue")
print str(emp)
Решение
Ваш код контрпродуктивен (извините, я должен это сказать).
Смысл фабрики в том, что вам не нужно знать класс вашего сконструированного объекта в том месте, где вы его создали.
Причина в том, что создание объекта создает пробел в объектно-ориентированной абстракции. Вы должны быть конкретными в создании объекта. Но иногда вы просто хотите создать объект с некоторым поведением, но кто-то другой должен (централизованно) решить, какой это конкретный класс.
Например, вы должны создать один тип объекта в 100 местах. Но позже вы можете узнать, что вы должны изменить класс - вам придется изменить все эти места.
Фабрика устранит эту потребность, определив одно место, которое вы должны изменить.
Самая простая фабрика была бы:
def fabricateAnotherObject(self, **kwargs):
return testClass(**kwargs)
Конечно, в некоторых ситуациях это может помочь. Поэтому некоторые фабрики могут также загружать имена классов из базы данных или другой конфигурации. Но самое простое решение - это жестко запрограммированная конструкция объекта - в нашем примере необходимо изменить только этот метод, если вы решите всегда вызывать этот метод.
Несколько более динамичное решение (без необходимости в БД):
class Factory(object):
def __init__(self, theClass):
self.theClass = theClass
def create(self, **kwargs):
self.theClass(**kwargs)
myFactory = Factory(testClass)
Экземпляр myFactory можно использовать в разных местах для создания правильных экземпляров. Проблема в том, как инициализировать myFactory - в каком-то специальном модуле ??
Другие советы
Фабричный шаблон предназначен для языков программирования, которые не допускают функции (и классы) в качестве значений первого порядка (например, C ++ или Java).
Идея состоит в том, что вы передаете экземпляр " фабрики " класс в качестве аргумента некоторой функции (или метода или конструктора), которая затем используется для создания новых экземпляров объекта (обычно это экземпляры некоторого определенного подкласса суперкласса, который известен заранее).
В Python вы можете просто передать класс (поскольку классы (и функции) также являются объектами).
Ваш фабричный метод должен выглядеть следующим образом:
def fabricateAnotherObject(self, obj, *args):
return apply(obj, args)
apply () принимает список аргументов. Принимая * args в вашем методе fabricateAnotherObject, вы используете все параметры, кроме obj, в виде списка, который можно передать в apply ().
См. также type () в docs.python.org/library/functions:
тип (имя, основание, дикт)
Вернуть объект нового типа. По сути, это динамическая форма выражения класса. Строка имени является именем класса и становится атрибутом __name__; кортеж base перечисляет базовые классы и становится атрибутом __bases__; а словарь dict - это пространство имен, содержащее определения для тела класса и становится атрибутом __dict__. Например, следующие два оператора создают идентичные объекты типа:
class X(object):
a = 1
X = type('X', (object,), dict(a=1))
Короткую реальную программу с одним использованием фабрик (компактное создание множества специальных диктов) см.
ofc2.py .
Эксперты, больше примеров, пожалуйста?