如何创建一个隐藏的工厂?

时间:2014-02-04 05:04:53

标签: python

我知道它已被覆盖过,但我只是没有得到它......

我想创建一个用文件名调用的类,但是,根据文件名的扩展名,它会变换为几个子类中的一个。它认为它是一个工厂模式,我在使用静态方法之前就已经这样做了,但我现在正在尝试使用基类的常见实例来完成它。这可能吗?

 >>> foo = FileClass('foo.txt')
 >>> type(foo)
 <type 'TextFileClass'>

 >>> foo = FileClass('foo.rtf')
 >>> type(foo)
 <type 'RTFFileClass'>

这不是实际产量,而是我希望实现的目标。我正在尝试疯狂的东西,必须远离赛道。目前我已经在__new__中实施了FileClass例程,但似乎不对。似乎有很多方法可以做到这一点?什么是正确的?

3 个答案:

答案 0 :(得分:4)

为什么不使用工厂功能?

class BaseFile(object):
    """Inherit these common methods and properties"""
    def __init__(self, fname):
        self.fname = fname

    def is_pretty(self):
        NotImplemented

class TextFileClass(BaseFile): 
    def is_pretty(self):
        return False

class RTFFileClass(BaseFile):
    def is_pretty(self):
        return True

def createFileClass(fname):
    if fname.endswith('.txt'):
        return TextFileClass(fname)
    elif fname.endswith('.rtf'):
        return RTFFileClass(fname)
    else:
        raise Exception, 'unknown file format'

FileClass = createFileClass

产地:

>>> foo = FileClass('foo.txt')
>>> type(foo)
<class '__main__.TextFileClass'>

>>> foo = FileClass('foo.rtf')
>>> type(foo)
<class '__main__.RTFFileClass'>

答案 1 :(得分:2)

使用__new__执行此操作的主要问题是,如果FileClass.__new__调用TextFileClass构造函数,TextFileClass如何__new__将实例转到cls返回?

要解决此问题,我们可以测试__new____new__的内容,因此我们不会干扰子类“def __new__(cls, filename): if cls is FileClass: return cls._factory(filename) return super(FileClass, cls).__new__(cls, filename)

FileClass('foo.txt')

当调用__init__时,如果__new__的实例是FileClass,则Python会对TextFileClass.__new__('foo.txt')返回的对象调用TextFileClass('foo.txt'),因此我们必须使用@classmethod def _factory(cls, filename): if filename.endswith('.txt'): return TextFileClass.__new__(filename) elif filename.endswith('.rtf'): return RTFFileClass.__new__(filename) ... 而不是{{1}}:

{{1}}

总而言之,以这种方式做事可能不值得。工厂功能或工厂方法更容易正确。

答案 2 :(得分:0)

如果FileClass不能是工厂函数,则可以应用Handle/Body模式(或派生的Envelope/Letter模式)让FileClass实例化实现类,将它保存在字段中并且代理方法调用它。消费者不会在变量类型中看到子类,但接口将存在,这是重要的事情。