我所处的场景是,我想重构几个具有相同和/或相似方法的类。类的数量大约为20个,类似方法的数量大约为15个。在这个空间中存在各种各样的组合,这就是为什么我有点不愿意用继承来解决这个问题
代码是由comapi控制的另一个应用程序的包装器的一部分。包装器又是在我工作的公司内部分发的包的一部分。因此类的接口必须保持不变(为了向后兼容)
此示例演示了这些类的一些非常简化的版本:
class FirstCollectionLike:
def __init__(self):
self._collection = list()
def add(self, arg):
self._collection.append(arg)
def remove(self, index):
del self._collection[index]
class SecondCollectionLike:
def __init__(self):
self._collection = list()
self._resource = some_module.get_resource()
def start(self):
some_module.start(self.resource)
def add(self, arg):
self._collection.append(arg)
def remove(self, value):
self._collection.remove(value)
class SomeOtherClass:
def __init__(self):
self._some_attribute = 0
self._resource = some_module.get_resource()
def add(self, value):
self._some_attribute += value
def start(self):
some_module.start(self._resource)
有什么设计模式可以帮助我解决这个问题吗
我最初的想法是创建方法类,如Add
、RemoveByIndex
和RemoveByName
,实现__call__
,如下所示:
class Add:
def __init__(self, owner):
self.owner = owner
def __call__(self, item):
self._collection.append(item)
class AddAndInstantiate:
def __init__(self, owner, type_to_instantiate):
self.owner = owner
self.type_to_instantiate = type_to_instantiate
def __call__(self, name):
self._collection.append(type_to_instantiate(name))
然后将这些类的实例作为实例属性分配给它们各自的所有者对象:
class RefactoredClassOne:
def __init__(self):
self.add = Add(self)
self.remove = RemoveByIndex(self)
class RefactoredClassTwo:
def __init__(self):
self.add = AddAndInstantiate(self, SomeClass)
self.remove = RemoveByName(self)
通过这种方式,我可以很容易地将任何方法添加到类中,并在需要时为方法类提供一些参数(如上面示例中要实例化的类的类型)。缺点是跟踪正在发生的事情有点困难,如果方法是以这种方式实现的,那么我们使用的自动文档生成(sphinx)就不起作用
这是不是一个糟糕的方法?有哪些替代方案
首先,如果你的类像你的例子建议的那样简单,我不确定OOP是不是合适的工具。您的类所做的只是重命名几个基本调用。这是一个无用的抽象,我认为这是一个糟糕的做法(为什么要强迫我查看
SecondClassCollectionLike.py
文件来发现.add()
实际上是一个错误命名的append
,而我的集合实际上是一个具有奇特名称的list
?)在这种情况下,我认为功能性方法可能更好,而工作流,例如:
如果它看起来像
如果您的类实际上更复杂,并且您真的希望保持OOP方法,那么我认为this solution很可能接近您的解决方案和您想要的
我们的想法是要有一个模块来保存逻辑。例如一个
_collection_behaviour.py
模块,它包含add()
、remove()
、increment()
或其他什么。以及_runtime.py
模块,它保存start()
、stop()
等逻辑通过这种方式,您可以拥有从这些模块中退出行为的类:
但是我不认为让这些函数类实现
__call__
有什么意义,如果它们只实现了__call__
相关问题 更多 >
编程相关推荐