n层架构是否打破了封装的OO概念

时间:2009-02-27 05:15:33

标签: design-patterns oop architecture n-tier-architecture

我有一个带有表示层,业务层,DAL和业务对象层的n层应用程序。分离对象和写在对象上的操作会破坏面向对象的封装概念。

4 个答案:

答案 0 :(得分:2)

没有。考虑“封装”的含义:类的实现细节隐藏在类的接口(消息或方法)之后。

事实上,您可以直接从OO原则和Parnas定律推导出n层架构:模块应该封装可能发生变化的内容。表示层封装了创建“可见”界面的细节;中间层是企业本身的模型;以及后端访问持久数据存储的细节。

答案 1 :(得分:1)

举个例子,摘自this article

public class Position
{
  public double distance( Position position )
  {
    // calculate and return distance...
  }

  public double heading( Position position )
  {
    // calculate and return heading...
  }

  public double latitude;
  public double longitude;
}

根据同一篇文章,这是一个很好的封装示例,因为捆绑了对该数据执行的数据和操作。请注意,此处的封装不保证数据隐藏或保护。

相比之下,Steve McConnell在Code Complete(第2版,第6.2节,良好封装)中会认为封装被破坏了,因为成员数据暴露了。

在您的情况下,如果您的数据对象和操作它们的对象是分开但没有公共字段,则根据第一个定义打破封装,但不一定在第二种情况下。所以我们有两种截然不同的观点。有人说数据隐藏不是封装的一部分,另一个来源说数据隐藏是封装的重要部分。

数据隐藏可被视为信息隐藏的一部分,这是表明您应隐藏复杂设计决策和变更源的原则。普遍的共识似乎是封装被视为信息隐藏的一种表现形式,包括数据隐藏。

或者,正如Wikipedia所说:

  

经常使用术语封装   与信息互换   躲了起来。并非所有人都同意   两者之间的区别;   人们可能会认为信息隐藏为   是原则和封装   是技术。一个软件模块   通过封装来隐藏信息   信息到模块或其他   提供界面的构造。

但是......本段后面的参考文献与第一个例子的文章相同,所以即使是维基百科也在这里混淆了一些东西。此外,在这里使用“区别”这个词似乎是错误的。

最后不得不说这个有点蹩脚,但是封装和信息隐藏的术语是重载的,所以这一切都取决于来源。在你的情况下,我会坚持封装的定义为“隐藏抽象背后的实现细节”。因此,您不必打破封装。

答案 2 :(得分:0)

AP真是太棒了!

在某些情况下,我同意将单个操作分解为多个对象确实会对封装产生负面影响。事实上,我认为这是我在许多网络架构中看到的一个大问题。

另一方面,某些事情对于分解是有用的,例如作为向数据库发送查询的对象等。

我认为在许多情况下,有一个论点是要更好地“封装”网页,以便更多的功能包含在单个对象或更少的对象中。因此,更多的是“以页面为中心”的方法,而不是将逻辑分散到大量的类中。

我认为这是一个至关重要的问题,我们总是要问自己我们设计的每个系统 - 抽象多少?要具体多少钱?如何有效地将系统分解为类。

答案 3 :(得分:-1)

两者不一样。体系结构更多地是指模块(类的组)。封装是指隐藏类的内部工作。如果您足够好地设计系统,则可以同时拥有两者。

您可能需要注意的是明确界定责任分离。只要您清楚每个模块/层的用途,并具体说明每个类的功能(以及该类的每个方法的作用),那么您应该能够拥有一个好的设计。

我只是在这里推测,但在设计模块接口时,您可能对facade design pattern感兴趣。

关于下面的评论,逻辑肯定应该在员工类本身。我会质疑业务对象的单独层的逻辑。定义像“员工”这样的类通常是一种诱惑,因为它们模拟现实世界的对象或概念。但是,您定义类的动机不应该是“建模现实世界的对象”。

您应该定义模块的用途(为什么您有业务逻辑层?包含所有业务逻辑。)然后将您需要的内容放在那里。如果“Employee”类是需要计算业务逻辑的类,那么它应该进入业务逻辑类。如果没有,那么它应该进入你的业务对象类(无论那是什么)。如果它需要做两件事,因此可以分为两层,那么考虑将它分成两个类 - 记住你的对象不需要模拟现实世界的事物。 Robert C Martin建议定义你的类,使类的边界成为目的的边界。