Factory Дизайн-шаблон
Я пытаюсь реализовать шаблон дизайна Factory и сделал это до сих пор.
import abc
class Button(object):
__metaclass__ = abc.ABCMeta
html = ""
def get_html(self, html):
return self.html
class ButtonFactory():
def create_button(self, type):
baseclass = Button()
targetclass = type.baseclass.capitalize()
return targetclass
button_obj = ButtonFactory()
button = ['image', 'input', 'flash']
for b in button:
print button_obj.create_button(b).get_html()
Выход должен быть HTML всех типов кнопок.
Я получаю ошибку, подобную этой
AttributeError: 'str' object has no attribute 'baseclass'
Я пытаюсь реализовать класс, который имеет различные варианты, такие как ImageButton, InputButton и FlashButton. В зависимости от места, возможно, потребуется создать другой html для кнопок
Ответы
Ответ 1
Вы пытаетесь вызвать baseclass
атрибут str
, который не существует, потому что b
получает строковые значения (один из ['image', 'input', 'flash']
).
Если вы хотите создать объект в соответствии со строкой, представляющей его имя, вы можете использовать словарь globals()
, который содержит сопоставление между именами переменных и их значениями.
class Button(object):
html = ""
def get_html(self):
return self.html
class Image(Button):
html = "<img></img>"
class Input(Button):
html = "<input></input>"
class Flash(Button):
html = "<obj></obj>"
class ButtonFactory():
def create_button(self, typ):
targetclass = typ.capitalize()
return globals()[targetclass]()
button_obj = ButtonFactory()
button = ['image', 'input', 'flash']
for b in button:
print button_obj.create_button(b).get_html()
EDIT:
Использование globals()
или locals()
также не является хорошей практикой, поэтому, если возможно, лучше создать сопоставление между соответствующими объектами и их именами, например:
button_objects = {'image':Image,'flash':Flash,'input':Input}
и замените create_button
на:
def create_button(self, typ):
return button_objects[typ]()
Ответ 2
Здесь ваша ошибка возникает из:
button = ['image', 'input', 'flash'] # button contains strings
for b in button: # b is a string
create_button(b) # argument 'type' is a string
type.baseclass... # hence the AttributeError
В вашем списке button
должны быть указаны объекты с атрибутом baseclass
, а не их имена в виде строк. Кроме того, вы не должны использовать type
в качестве имени переменной, так как он изменяет стандартную библиотечную функцию Python type()
.
Ответ 3
Предполагая, что вам нужно создать экземпляры кнопок на основе строки времени исполнения, альтернативой вашему классу Button и factory будет просто иметь словарь имен по типам (как предложил chepner):
buttonTypes = {"image" : Image,
"input": Input,
"flash" : Flash}
button = buttonTypes[name]()
print button.html
(nb это было напечатано прямо здесь, могут быть некоторые ошибки в деталях). Поскольку Python утилит, вам может не понадобиться базовый тип.