Python 工厂设计模式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21025959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 21:50:03  来源:igfitidea点击:

Factory Design Pattern

pythondesign-patterns

提问by ajknzhol

I am trying to implement Factory Design Pattern and have done this far till now.

我正在尝试实施工厂设计模式,并且到目前为止已经完成了这项工作。

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()

The output should be the HTML of all your button types.

输出应该是所有按钮类型的 HTML。

I get the error like this

我得到这样的错误

AttributeError: 'str' object has no attribute 'baseclass'

I am trying to implement a class which has different variations, such as ImageButton, InputButton and FlashButton. Depending on the place, it may need to create different html for the buttons

我正在尝试实现一个具有不同变体的类,例如 ImageButton、InputButton 和 FlashButton。根据位置,可能需要为按钮创建不同的 html

采纳答案by Elisha

You are trying to call baseclassattribute of str, which does not exist, because bgets string values (one of ['image', 'input', 'flash']). If you want to create an object according to a string representing its name, you can use the globals()dictionary, which holds a mapping between variable names and their values.

您正在尝试调用不存在的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: Using globals()or locals()is also not a good practice so, if you can, it is better to create a mapping between the relevant objects and their names, like this:

编辑:使用globals()orlocals()也不是一个好习惯,因此,如果可以,最好在相关对象及其名称之间创建映射,如下所示:

button_objects = {'image':Image,'flash':Flash,'input':Input}

and replace create_buttonwith:

并替换create_button为:

def create_button(self, typ):        
    return button_objects[typ]()

回答by jonrsharpe

Here is where your error comes from:

这是您的错误的来源:

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

Your list buttonneeds to contain objects that have the baseclassattribute, not their names as strings. Also, you shouldn't use typeas a variable name, as it shadows a Python standard library function type().

您的列表button需要包含具有baseclass属性的对象,而不是它们的名称作为字符串。此外,您不应将其type用作变量名,因为它会影响 Python 标准库函数type()

回答by Pete

Assuming you need to create button instances based on a runtime string, an alternative to your Button class and factory would be to simply have a dictionary of names to types (much as chepner suggested):

假设您需要基于运行时字符串创建按钮实例,则 Button 类和工厂的替代方法是简单地拥有一个名称到类型的字典(就像 chepner 建议的那样):

buttonTypes = {"image" : Image,
               "input": Input,
               "flash" : Flash}

button = buttonTypes[name]()
print button.html

(nb this was typed straight into here, there may be some mistakes in the detail). Because Python is duck-typed you may well not need a base type.

(注意这里是直接输入的,细节上可能有一些错误)。因为 Python 是鸭子类型的,所以您可能不需要基本类型。