【问题标题】:aggregation breaks encapsulation聚合破坏封装
【发布时间】:2012-11-28 17:47:20
【问题描述】:

我一直在阅读书籍,试图了解聚合和组合的各个方面。但是,我发现聚合可以增强松散耦合,但也可以破坏封装。

增强松散耦合。

public class Car{
    private Engine engine;
    Car(Engine e){
        this.engine=e;
    }
}

上面的引擎类的任何实现都可以在创建时创建并推送到 Car 对象,并且由于 Engine 实例可以在没有汽车的情况下生存,因此它是一个完美的聚合示例。 (这个例子可能不是一个很好的现实例子,但我想我的观点)

现在客户端代码可以完全控制引擎对象,因此它可以更改传递给 Car 的引擎对象的少数状态,并且 Car 的实现会破坏封装,因为它的对象或状态(即 Engine)是 no more 在汽车中具有正确的完整性。

我的理解正确吗?

【问题讨论】:

  • 这有点取决于封装,你不想改变对象的状态,而是想操作对象。所以使用引擎而不是 engine.setOn(boolean) 你有 engine.turnOn()。如果您只希望汽车能够在引擎上运行,那么在构造函数中您将克隆对象以限制访问。 this.engine = (Engine)e.clone();汽车上的其他操作可能是 removeEngine 然后您可以访问引擎但汽车不再有一个。
  • IMO,我认为客户端无法控制 Engine 对象。我想会有一个更高级别的类,称为 Manufacturer,它会创建正确的 Engine 对象并将其设置为特定 Car 对象的引擎。
  • 我认为他指的是创建汽车的过程在不应该引用引擎时会引用引擎。
  • @Vaibhav,我同意一个设计合理的类应该像你说的那样,但是制造商在这种情况下成为客户,他可以在 Car 之后修改 Engine 对象的某些状态创建,然后汽车对象将呈现损坏。你不这么认为吗?
  • @BevynQ,然后我会想象整个 Engine 类是只读的。

标签: java encapsulation aggregation


【解决方案1】:

Engine 可以被Car 破坏,只有它是可变的,即汽车可以改变引擎的状态。但是,您可以定义不可变类 Engine(只有 getter 可以访问不改变状态的状态和业务方法)或创建由类 EngineImpl 实现的接口 EngineEngineImpl 不是一成不变的。它包括可以更改其状态的功能。然而,它实现了接口Engine,它只向客户端公开“不可变”方法。所以,汽车不能改变隐藏在只读界面Engine后面的EngineImpl的状态。在这种情况下,封装不会被破坏。

你是对的:这不是现实世界的例子:在现实世界中,驾驶员通过他的汽车提供的接口控制引擎并且可以破坏引擎:(

【讨论】:

  • 同意,为您 +1。只是一个疑问,非常微不足道,一个可变的实现会破坏 Car ,而不是 Engine ,对吧?
【解决方案2】:

这里,松散耦合是针对 Car 和 Engine 之间的关系。

尽管汽车通过其构造函数接受任何引擎,但我相信汽车不会通过 getter 方法暴露引擎。

此构造函数应具有适当的访问控制/级别,并由负责将引擎与汽车集成的工厂或其他创建模式使用。

允许 Car 的客户端访问 Engine 应该是通过 Car 的接口。

【讨论】:

  • 我想你错过了我的意思,让我这样说吧。引擎 e = new EngineImpl();汽车 c = 新车(e); e.setSomethingOnEngine();// 这可能会破坏汽车的行为
  • e.setSomethingOnEngine() 通常不会由任何工厂或创建模式完成。也许,Builder 可以构建引擎,但它不会在引擎被创建并提供注入 Car 后更改引擎。如果是这样,那么创建模式代码就违反了原则。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
  • 1970-01-01
  • 2020-01-15
  • 1970-01-01
相关资源
最近更新 更多