Python - 重构在不同类中发现的类似方法

2024-04-26 08:02:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我所处的场景是,我想重构几个具有相同和/或相似方法的类。类的数量大约为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)

有什么设计模式可以帮助我解决这个问题吗

我最初的想法是创建方法类,如AddRemoveByIndexRemoveByName,实现__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)就不起作用

这是不是一个糟糕的方法?有哪些替代方案


Tags: 方法selfaddinitdefargsomestart
1条回答
网友
1楼 · 发布于 2024-04-26 08:02:05

首先,如果你的类像你的例子建议的那样简单,我不确定OOP是不是合适的工具。您的类所做的只是重命名几个基本调用。这是一个无用的抽象,我认为这是一个糟糕的做法(为什么要强迫我查看SecondClassCollectionLike.py文件来发现.add()实际上是一个错误命名的append,而我的集合实际上是一个具有奇特名称的list?)

在这种情况下,我认为功能性方法可能更好,而工作流,例如:

a = SecondClassCollectionLike()
a.add("x")
a.add("y")
a.remove(0)
a.start()

如果它看起来像

a = list()
a.append("x")
a.append(y)
del a[0]
somemodule.start()

如果您的类实际上更复杂,并且您真的希望保持OOP方法,那么我认为this solution很可能接近您的解决方案和您想要的

我们的想法是要有一个模块来保存逻辑。例如一个_collection_behaviour.py模块,它包含add()remove()increment()或其他什么。以及_runtime.py模块,它保存start()stop()等逻辑

通过这种方式,您可以拥有从这些模块中退出行为的类:

calss MyClass():
    def __init__(self):
        self._collection = list()

    from ._collection_behaviour import add
    from ._collection_behaviour import remove
    from ._runtime import start

但是我不认为让这些函数类实现__call__有什么意义,如果它们只实现了__call__

相关问题 更多 >