Подтвердить что ты не робот

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 для кнопок

4b9b3361

Ответ 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 утилит, вам может не понадобиться базовый тип.