【问题标题】:Proper way to subclass in python for decoupling in client code在 python 中进行子类化以在客户端代码中解耦的正确方法
【发布时间】:2019-08-13 18:11:45
【问题描述】:

我遇到了一些有趣的设计问题。

我有一些抽象类,我们把它命名为ServiceClass

假设我有 2 个子类,分别命名为 CoolServiceClassAmazingServiceClass,它们都继承自 ServiceClass

class ServiceClass(ABC):
    @abstractmethod
    def do_something(self):
        pass


class CoolServiceClass(ServiceClass):
    def do_something(self):
        return 'Cool!'

    def do_nothing(self):
        return 'Nothing!'


class AmazingServiceClass(ServiceClass):
    def do_something(self):
        return 'Amazing!'

    def just_do_it(self):
        return 'Nope'

我想编写客户端代码,但我不希望它与客户端代码中的子类之一耦合。我不希望客户端代码能够使用任何方法just_do_itdo_nothing,因此我将能够轻松地在它们的实现之间进行替换。我知道 python 是鸭式语言,但我仍然想知道处理这种情况的正确方法是什么?

我想到的一个解决方案是使用某种看起来像这样的代理类:

class ProxyServiceClass(ServiceClass):
    def __init__(self, service_class):
        self.service_class = service_class

    def do_something(self):
        return self.service_class.do_something()

然后客户端代码将如下所示:

service_class1 = ProxyServiceClass(CoolServiceClass())
service_class2 = ProxyServiceClass(AmazingServiceClass())

现在,如果我尝试使用 just_do_itdo_nothing 中的任何一种方法,我会遇到异常。

我对这个解决方案有点怀疑,因为我还没有看到类似的解决方案,我很乐意听取您的意见。

谢谢!

【问题讨论】:

  • 根据您的描述,客户端代码应该动态调用所有子类的组合功能 - 您需要某种组合
  • 所以你打算将do_nothing设为“私有”?在 python 中真的没有这样的东西,一切都是可以访问的。即使使用您的解决方案,用户也可以使用service_class1.service_class.do_nothing()
  • @RonSerruya,我想要的是只有抽象类中定义的方法在客户端可用,至少子类方法的使用不会“明显”。
  • 在静态类型语言中,您只需要一个ServiceClass 的实例。尽管所述实例实际上可能是AmazingServiceClass 的实例并且可以访问just_do_it,但客户端 无法假设,因此无法使用它。在 Python 中,做到这一点的方法是简单地记录任何特定的子类都不能指望。也就是说,客户端应该只使用ServiceClass提供的接口。

标签: python


【解决方案1】:

如果do_nothing 是私有方法(即不能从类外部访问),请将其重命名为__do_nothing (Why are Python's 'private' methods not actually private?)

如果您希望 一些 外部用户可以访问它,而不是其他用户,那么除了您描述的包装器之外,我没有看到其他解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多