是'封装'帮助并行开发多个模块?

时间:2015-08-02 08:14:41

标签: java oop encapsulation abstraction data-hiding

经过SO问题后,我了解到了,

封装是关于保护不变量并隐藏实现的详细信息。

抽象接口实现分离。

从教室java training,我了解到, Encapsulation 具有以下优势,

  

为什么封装是你的朋友?

     

[1]实现与功能无关。一个程序员    拥有该界面文档的人可以实现新版本    模块或ADT独立。一个新的,更好的实现可以    替换旧的。

     

[2]封装阻止Doug编写破坏a的应用程序    模块的内部数据。在实际编程中,封装    减少调试时间。很多。

     

[3] ADT可以保证保留其不变量。

     

[4]团队精神。一旦你严格定义了模块之间的接口,    每个程序员都可以独立实现一个模块    访问其他模块。一个庞大而复杂的编程项目可以    分成几十块。

     

[5]文档和可维护性。通过定义一个明确的    接口,您可以让其他程序员更容易修复错误    在你离开公司几年后出现。许多错误是由于    模块之间无法预料的交互。如果有明确的话    每个接口的规范和每个模块的行为,错误都是    更容易追踪。

     

[6]当你的项目不起作用时,更容易找出哪个    队友应该受到责备。

问题1:

Wrt Point1 (上图)说," 一个新的,更好的实现可以取代旧的。"。这是抽象的目标,但不是封装。我是对的吗?

问题2:

Wrt Point 4 (上图), Encapsulation 如何帮助程序员独立实现模块而无需访问其他模块?模块的并行实现与 Encapsulation 有什么关系?因为封装是关于保护 in-variants 。这个answer也支持我的论点

2 个答案:

答案 0 :(得分:0)

(1)接口应该被广义地解释;因为它具有一些特定的技术含义,我倾向于更喜欢术语契约(来自"design by contract")来表示同样的事情。它是如何与特定模块(或模块类型)交互的正式规范。一个很好的例子是Collections API; List通常是ArrayList,但它可以是LinkedListImmutableList,或者像懒惰数据库代理一样更具异国情调。我几乎从不关心我的代码是什么类型的特定类型;我只是与List界面进行互动。

(2)如果使用实际的Java接口(或等效的接口),则在开发过程中创建要使用的组件的模拟或脚手架版本非常容易。例如,我刚刚实现了一个发送电子邮件的系统。当我让系统的其余部分准备好实际发出要发送的订单时,我使用了一个伪造的邮件服务,它只是编写了假装发送邮件的日志消息。这样,我可以测试我的系统中应该调用邮件服务的部分是否正常工作,而不是实际发送邮件。

在更大的范围内,我使用Spring MVC来处理我的应用程序的Web层。 Spring MVC与Servlet API交互以与servlet容器进行交互,servlet容器本质上是Web服务器本身。 Spring团队不需要了解有关服务器的任何其他信息;几个不同的servlet容器(Tomcat,Jetty,Undertow,WebLogic)由不同的团队编写,但由于每个人都使用通用接口,因此他们无需进一步协调他们的开发工作。

答案 1 :(得分:0)

要回答这个问题,我们必须澄清我们所说的"抽象"和"封装"。

维基百科defines抽象如下:

  

主要意义上的抽象是一个概念过程,通过这个过程,一般规则和概念来自特定例子的使用和分类,文字("真实"或"具体")符号,第一原则或其他方法。 "抽象"是这个过程的产物 - 一个概念,作为所有从属概念的超分类名词,并将任何相关概念作为一个组,字段或类别连接起来。

for mathematics

  

数学中的抽象是提取数学概念的基本本质的过程,消除对最初可能与之连接的现实世界对象的任何依赖,并将其概括为使其具有更广泛的应用或其他抽象描述之间的匹配等效现象

computer science

  

在计算机科学中,抽象是一种管理计算机系统复杂性的技术。它的工作原理是建立一个人与系统交互的复杂程度,从而抑制当前级别以下更复杂的细节。

总之,抽象是一般化的过程,抽象是这个过程的结果。

通过概括,我们使其更广泛适用(可重复使用)。例如,如果我有一个对人进行排序的方法,以及一种对猫进行排序的方法,我可以概括一种方法来对可以成对比较的任何事物进行排序。 该方法有许多应用。这是一个有用的抽象。

通过概括某些事物,我们将整组事物视为一样,不再关心我们正在考虑哪些具体事物。在上面的例子中,我抽象了 over 要排序的对象类型,并抽象远离它们的内部表示。

因此,抽象与信息隐藏的概念密切相关,维基百科defines如下:

  

在计算机科学中,信息隐藏是计算机程序中最有可能改变的设计决策的隔离原则,因此如果设计决策被改变,则保护程序的其他部分不被广泛修改。保护涉及提供稳定的接口,以保护程序的其余部分免受实现(最有可能改变的细节)。

     

另一种方式是,信息隐藏是指使用编程语言功能(如私有变量)或显式导出策略阻止类或软件组件的某些方面被其客户端访问的能力。

也就是说,信息隐藏是一种强制抽象的方法。我们不仅仅允许我们的呼叫者在抽象中思考,我们强迫他们隐藏他们不应该考虑的具体事物的知识。

有了这个,我们终于可以谈论封装,维基百科defines如下:

  

封装是将数据和功能打包到单个组件中。尽管还存在其他替代方案,但是使用大多数面向对象编程语言中的类来支持封装的特征。它允许通过构建不可穿透的墙来选择性地隐藏对象中的属性和方法,以保护代码免受意外损坏。

也就是说,封装是一种信息隐藏(我们隐藏字段或方法)。

考虑到这个理论,关于你的问题:

  

Wrt Point1(上图)说,"一个新的,更好的实现可以取代旧的。"。这是抽象的目标,但不是封装。我是对的吗?

由于封装可用于强制执行抽象,因此可以促进其使用,因此可以有助于获得收益。实际上,这就是封装的目的。

但是,你是正确的,没有抽象的封装不会促进实现交换。这种封装未能达到其目的;它被滥用了。

也就是说,您引用的文章默认假设已正确使用封装。

  

Encapsulation如何帮助程序员独立实现模块而无需访问其他模块?这个模块的并行实现如何与Encapsulation有关?因为封装是关于保护变体。

如果通过封装来保护不变量,则调用代码可能不需要知道这个不变量。如果是这样,则不变量被抽象掉了,调用代码的开发不受这个不变量的影响,即其他模块可以独立于该不变量而开发。