更少的API或更多的封装?
问题描述:
3类,A包含B,B包含C.所以用户要使用一些C的服务,有两种选择:更少的API或更多的封装?
首先,更多的封装:中
class A:
def newMethod(self):
self.b.newMethod()
class B:
def newMethod(self):
self.c.newMethod()
class C:
def newMethod(self):
#do something
pass
a.newMethod()
呼叫服务C直接:
class A:
pass
class B:
pass
class C:
def newMethod(self):
#do something
pass
b = a.b
c = a.c
c.newMethod()
一般来说,我从书本上学到的东西告诉我,第一选择更好。
但是当C有许多方法暴露给外部用户时,第二个选择似乎更合理。在第一个设计中,A和B没有真正有用。
您会选择什么?
答
让你的对象为你做事,而不是要求他们提供他们的数据和做它的东西。
如果c
在您的例子暴露了很多方法,我建议你不应该你的客户公开这些以a
和,而是a
和b
应共同努力,用代表的这些方法客户。
问题的一个很好的指标是一个包含数据并为这些数据项提供getter的类,以及访问该数据然后执行工作(DAO除外)的客户端代码。在这种(常见的)场景中,类很可能不应该暴露该数据(也可能是破坏封装),而是为该客户端(通过具有该功能,或者可能是一些可注入的策略对象)执行该项工作。
查看Law of Demeter(链接的文档看起来相当干燥和学术,令人遗憾),它提供了关于对象和成员应该如何通信的一些很好的指导。
当然,一般来说,书会说。 但让我解释更多。这不仅是因为C公开了很多方法,这是因为还有C1,C2,C3,它们负责为外部用户代码提供服务。 当然,我可以隐藏所有的B,C,C1并向A中添加很多方法,所以用户代码看不到我的库的内部部分 但是,这实际上并没有意义。 A只是直接向B和其他负责的类传递参数。 根据SRP,A应该只有一个责任,A不应该做B或C的工作,它只是让用户找到一个地方B – lilyonwind 2009-09-09 13:04:52
隐藏B/C/C1/C2的另一个问题是用户代码无法访问事件的他们。这意味着A从图书馆内部向外部传送每一个事件,我认为很多无用的工作。 – lilyonwind 2009-09-09 13:11:11