工厂模式——使用静态方法进行选择
Factory pattern - choosing using static method
我想在我的 python 代码中为两种不同的文件格式使用工厂模式。
是否可以定义一个静态方法来选择我的新 class,而无需在基础 class 中定义 init 或 new ]?
类似于:
Class Field(fileName):
@static method
def chooseClass(fileName):
if '.grb' in fileName:
return FieldGrib(fileName)
if '.nc' in fileName:
return FieldnetCDF(fileName)
else:
raise valueError('File format not supported')
是否可以在不调用任何方法的情况下,在调用 Field(fileName) 后立即动态分配新的 class?
下面的答案确实解决了我的问题,但我最终得到了 super 的递归循环,你能帮我指出问题吗?
class Field(object):
def __new__(cls, fieldFile):
if '.grb' in fieldFile:
return FieldGrib(fieldFile)
else:
raise ValueError('no support for other formats')
def __init__(self, fieldFile):
print fieldFile
class FieldGrib(Field):
def __init__(self, fieldFile):
# read Field, opening fieldFile if required
super(FieldGrib, self).__init__(fieldFile)
你的工厂模式代码看起来没问题。
对于"dynamically allocate the new class as soon as Field(fileName) is called",你可以简单地做:
def Field(fileName):
if '.grb' in fileName:
return FieldGrib(fileName)
if '.nc' in fileName:
return FieldnetCDF(fileName)
else:
raise ValueError('File format not supported')
或者如果出于某种原因你真的需要 Field
作为 class,你可以按如下方式使用 __new__
(确保 Field 是 new-style class,即如果使用 Python 2,继承 object
):
class Field(object):
def __new__(cls, fileName):
if '.grb' in fileName:
return FieldGrib(fileName)
if '.nc' in fileName:
return FieldnetCDF(fileName)
else:
raise ValueError('File format not supported')
关于你的第二个问题,我认为不使用 new 是不可能做你想做的事的,除非你同意将它变成像 ferri 描述的那样的函数.如果您想维护 class 结构,您可以这样做。
Class Field(object):
def __init___(self):
pass
def __new__(cls, filename):
if '.grb' in fileName:
return FieldGrib(fileName)
if '.nc' in fileName:
return FieldnetCDF(fileName)
else:
raise valueError('File format not supported')
class FieldGrib(Object_To_Inherit_From)
def __init__(self, fileName):
super().__init__(fileName)
self.fileName = fileName
...etc.
编辑:
如果您想维护基础 class 的功能,您可以更改 FieldGrib class 和 FieldnetCDF class 上的继承 class,因为它们是什么return出厂 class。
编辑 2:
你不能从工厂继承class因为当你调用super时它会再次运行new,进入一个递归循环。工厂 class 就是一个工厂。它不应该继承任何东西。它只是指示 class 到 return。 FieldGrib 和 FieldGrib 应该继承自包含您想要的功能的 class,而不是 Field。如果字段仅用于创建其他内容,您可以创建一个名为
的私有字段 class
class _Field(object):
包含您想要的功能并且可以从中继承。但是不应该直接调用它。
这会将 FieldGrab 变成
class FieldGrib(_Field):
我想在我的 python 代码中为两种不同的文件格式使用工厂模式。 是否可以定义一个静态方法来选择我的新 class,而无需在基础 class 中定义 init 或 new ]?
类似于:
Class Field(fileName):
@static method
def chooseClass(fileName):
if '.grb' in fileName:
return FieldGrib(fileName)
if '.nc' in fileName:
return FieldnetCDF(fileName)
else:
raise valueError('File format not supported')
是否可以在不调用任何方法的情况下,在调用 Field(fileName) 后立即动态分配新的 class?
下面的答案确实解决了我的问题,但我最终得到了 super 的递归循环,你能帮我指出问题吗?
class Field(object):
def __new__(cls, fieldFile):
if '.grb' in fieldFile:
return FieldGrib(fieldFile)
else:
raise ValueError('no support for other formats')
def __init__(self, fieldFile):
print fieldFile
class FieldGrib(Field):
def __init__(self, fieldFile):
# read Field, opening fieldFile if required
super(FieldGrib, self).__init__(fieldFile)
你的工厂模式代码看起来没问题。
对于"dynamically allocate the new class as soon as Field(fileName) is called",你可以简单地做:
def Field(fileName):
if '.grb' in fileName:
return FieldGrib(fileName)
if '.nc' in fileName:
return FieldnetCDF(fileName)
else:
raise ValueError('File format not supported')
或者如果出于某种原因你真的需要 Field
作为 class,你可以按如下方式使用 __new__
(确保 Field 是 new-style class,即如果使用 Python 2,继承 object
):
class Field(object):
def __new__(cls, fileName):
if '.grb' in fileName:
return FieldGrib(fileName)
if '.nc' in fileName:
return FieldnetCDF(fileName)
else:
raise ValueError('File format not supported')
关于你的第二个问题,我认为不使用 new 是不可能做你想做的事的,除非你同意将它变成像 ferri 描述的那样的函数.如果您想维护 class 结构,您可以这样做。
Class Field(object):
def __init___(self):
pass
def __new__(cls, filename):
if '.grb' in fileName:
return FieldGrib(fileName)
if '.nc' in fileName:
return FieldnetCDF(fileName)
else:
raise valueError('File format not supported')
class FieldGrib(Object_To_Inherit_From)
def __init__(self, fileName):
super().__init__(fileName)
self.fileName = fileName
...etc.
编辑:
如果您想维护基础 class 的功能,您可以更改 FieldGrib class 和 FieldnetCDF class 上的继承 class,因为它们是什么return出厂 class。
编辑 2:
你不能从工厂继承class因为当你调用super时它会再次运行new,进入一个递归循环。工厂 class 就是一个工厂。它不应该继承任何东西。它只是指示 class 到 return。 FieldGrib 和 FieldGrib 应该继承自包含您想要的功能的 class,而不是 Field。如果字段仅用于创建其他内容,您可以创建一个名为
的私有字段 classclass _Field(object):
包含您想要的功能并且可以从中继承。但是不应该直接调用它。
这会将 FieldGrab 变成
class FieldGrib(_Field):