工厂模式 - 使用静态方法选择

时间:2018-04-13 08:29:52

标签: python factory-pattern

我想在我的python代码中使用一个工厂模式来获得两种不同的文件格式。 可以定义一个静态方法来选择我的新类,而不在基类中定义 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 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)

2 个答案:

答案 0 :(得分:0)

您的工厂模式代码看起来不错。

对于“一旦调用Field(fileName)就动态分配新类”,您可以这样做:

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作为类,可以使用__new__,如下所示(确保Field为new-style class,即如果使用Python 2,则继承{ {1}}):

object

答案 1 :(得分:-1)

关于你的第二个问题,我不相信可以在不使用的情况下做你想做的事情,除非你可以把它变成fferri描述的功能。如果你想维持类结构,你可以做的就是这个。

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.

编辑:

如果要维护基类中的函数,可以更改FieldGrib类和FieldnetCDF类上的继承类,因为它们是从工厂类返回的类。

编辑2:

您不能从工厂类继承,因为当您调用super时,它将再次运行 new ,进入递归循环。工厂类只是一个工厂。它不应该继承任何东西。它只是决定返回哪个类。 FieldGrib和FieldGrib应该从包含所需功能的类继承,而不是从Field继承。如果字段仅用于创建其他内容,则可以创建名为

的私有Field类
class _Field(object):

包含您想要的功能并且可以继承。它不应该被直接调用。

这会将FieldGrab变成

class FieldGrib(_Field):