我有一个带有表示层,业务层,DAL和业务对象层的n层应用程序。分离对象和写在对象上的操作会破坏面向对象的封装概念。
答案 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建议定义你的类,使类的边界成为目的的边界。