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
Factory Design Pattern
提问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 是鸭子类型的,所以您可能不需要基本类型。

