【发布时间】:2019-08-13 18:11:45
【问题描述】:
我遇到了一些有趣的设计问题。
我有一些抽象类,我们把它命名为ServiceClass
假设我有 2 个子类,分别命名为 CoolServiceClass 和 AmazingServiceClass,它们都继承自 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_it 或do_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_it 或 do_nothing 中的任何一种方法,我会遇到异常。
我对这个解决方案有点怀疑,因为我还没有看到类似的解决方案,我很乐意听取您的意见。
谢谢!
【问题讨论】:
-
根据您的描述,客户端代码应该动态调用所有子类的组合功能 - 您需要某种组合
-
所以你打算将
do_nothing设为“私有”?在 python 中真的没有这样的东西,一切都是可以访问的。即使使用您的解决方案,用户也可以使用service_class1.service_class.do_nothing() -
@RonSerruya,我想要的是只有抽象类中定义的方法在客户端可用,至少子类方法的使用不会“明显”。
-
在静态类型语言中,您只需要一个
ServiceClass的实例。尽管所述实例实际上可能是AmazingServiceClass的实例并且可以访问just_do_it,但客户端 无法假设,因此无法使用它。在 Python 中,做到这一点的方法是简单地记录任何特定的子类都不能指望。也就是说,客户端应该只使用ServiceClass提供的接口。
标签: python