我有一个类代表一个非常复杂的对象。可以通过多种方式创建对象:增量构建、通过解析不同格式的文本字符串以及通过分析二进制文件。到目前为止,我的策略如下:
让构造函数(
__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 的建议使用类方法,因为这(稍微)更复杂并且不会在那种情况下真的很买你,因为当这种情况发生时你必须改变这个方案中的两个类。当然,这也没什么坏处,因为您只需再更改一项作业即可。
