Skip to main content
 首页 » 编程设计

python之对象生成器模式

2025年05月04日14findumars

我有一个类代表一个非常复杂的对象。可以通过多种方式创建对象:增量构建、通过解析不同格式的文本字符串以及通过分析二进制文件。到目前为止,我的策略如下:

  • 让构造函数(__init__,在我的例子中)将所有内部变量初始化为None

  • 提供不同的成员函数来填充对象

  • 让这些函数将修改后的新对象返回给调用者,这样我们就可以执行 sd = SuperDuper().fromString(s)

例如:

class SuperDuper: 
    def __init__(self): 
        self.var1 = None 
        self.var2 = None 
        self.varN = None 
 
    ## Generators 
    def fromStringFormat1(self, s): 
        #parse the string 
        return self  
    def fromStringFormat2(self, s): 
        #parse the string 
        return self 
    def fromAnotherLogic(self, *params): 
        #parse params 
        return self 
    ## Modifiers (for incremental work) 
    def addThis(self, p): 
        pass 
    def addThat(self, p): 
        pass 
    def removeTheOtherOne(self, p): 
        pass 

问题是类(class)变得非常庞大。不幸的是,我不熟悉 OOP 模式设计,但我认为这个问题有更优雅的解决方案。将生成器函数从类中取出(以便 fromString(self, s) 变成 superDuperFromString(s) 是个好主意吗?

请您参考如下方法:

在您的情况下,依赖注入(inject)和控制反转可能是一个更好的主意。我们的想法是创建另一个类,其中包含您从所有这些不同来源中解析出的所有设置。然后子类可以定义方法来实际解析它。然后当你实例化类时,将设置类的实例传递给它:

class Settings(object): 
    var1 = None 
    var2 = None 
    var3 = None 
 
    def configure_superduper(self, superduper): 
        superduper.var1 = self.var1 
        # etc 
 
class FromString(Settings): 
    def __init__(self, string): 
        #parse strings and set var1, etc. 
 
class SuperDuper(object): 
    def __init__(self, settings): # dependency injection   
        settings.configure_superduper(self)  # inversion of control 
        # other initialization stuff 
 
sup = SuperDuper(object, FromString(some_string)) 

这样做的好处是更严格地遵守单一职责原则,该原则规定一个类应该只有一个(可能发生的)原因来改变。如果您更改存储这些字符串中的任何一个的方式,则该类也必须更改。在这里,我们针对每个数据源将其隔离到一个简单、独立的类中。

如果另一方面,您认为正在存储的数据比其存储方式更有可能发生变化,您可能希望按照 Ignacio 的建议使用类方法,因为这(稍微)更复杂并且不会在那种情况下真的很买你,因为当这种情况发生时你必须改变这个方案中的两个类。当然,这也没什么坏处,因为您只需再更改一项作业即可。