更少的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和,而是ab应共同努力,用代表的这些方法客户。

问题的一个很好的指标是一个包含数据并为这些数据项提供getter的类,以及访问该数据然后执行工作(DAO除外)的客户端代码。在这种(常见的)场景中,类很可能不应该暴露该数据(也可能是破坏封装),而是为该客户端(通过具有该功能,或者可能是一些可注入的策略对象)执行该项工作。

查看Law of Demeter(链接的文档看起来相当干燥和学术,令人遗憾),它提供了关于对象和成员应该如何通信的一些很好的指导。

+0

当然,一般来说,书会说。 但让我解释更多。这不仅是因为C公开了很多方法,这是因为还有C1,C2,C3,它们负责为外部用户代码提供服务。 当然,我可以隐藏所有的B,C,C1并向A中添加很多方法,所以用户代码看不到我的库的内部部分 但是,这实际上并没有意义。 A只是直接向B和其他负责的类传递参数。 根据SRP,A应该只有一个责任,A不应该做B或C的工作,它只是让用户找到一个地方B – lilyonwind 2009-09-09 13:04:52

+0

隐藏B/C/C1/C2的另一个问题是用户代码无法访问事件的他们。这意味着A从图书馆内部向外部传送每一个事件,我认为很多无用的工作。 – lilyonwind 2009-09-09 13:11:11