design-patterns - 访问者模式和违反封装

标签 design-patterns

void accept(CarElementVisitor *visitor) {
        visitor->visit(this);
    }
}

在这里,我们将一个对象传递给一个向它添加操作的函数。在这里,它违反了封装。它是好的面向对象设计吗?

最佳答案

如果通过对象内部发生变化时可能直接受影响的函数计数来衡量封装,那么该模式会减少 ConcreteElement 的封装。实现 Element::accept(Visitor) 时至少减少 1界面。如果ConcreteElement,封装可能会进一步减少。的接口(interface)需要扩展以提供操作以实现 ConcreteVisitor 的功能.

模式本身既不好也不坏,因为通常是上下文导致模式有利或不利。因此,设计师应该考虑模式的意图、动机、适用性和后果。访问者模式的目的是允许定义新的操作而不改变操作所在的类。虽然不能保证,但它可能会增加 Element 的相对封装。 -family 与将操作添加到 Element 相比本身。

例如,考虑操作想要检查 CarElement 的液位的情况。对象。没有访客,CarElement接口(interface)声明了 check_fluid_levels()功能:

CarElement                  { check_fluid_levels() }
Break: CarElement           { check_fluid_levels() }
WindshieldWiper: CarElement { check_fluid_levels() }
Wheel: CarElement           { check_fluid_levels() }

for e in car:
  e.check_fluid_levels()

虽然检查某些 CarElement 的液位可能是有意义的。喜欢 BreakWindshieldWiper ,它可能对所有 CarElement 都没有意义对象,例如 Wheel .尽管如此,Wheel 的相对封装由于check_fluid_levels() 已减少在 CarElement 上声明界面。

另一方面,如果使用访问者模式,那么只有检查液位有意义的元素才会提供 check_fluid_levels()。功能。
CarElement                  { accept(Visitor) }
Break: CarElement           { accept(Visitor); check_fluid_levels() }
WindshieldWiper: CarElement { accept(Visitor); check_fluid_levels() }
Wheel: CarElement           { accept(Visitor) }

FluidChecker: Visitor       { ... }

FluidChecker checker
for e in car:
  e.accept(checker)

accept() 的相对封装减少 1函数,相对封装比将操作添加到 CarElement 更好。 .考虑添加一个新操作来检查 CarElement 的排放水平s。在这种情况下,以上都不是 CarElement s 将提供一个有意义的 check_emissions()功能。对于访问者,新操作不会影响封装级别;另一方面,如果将操作添加到 CarElement,封装级别会发生变化。 .

这是一张图表,列出了可以访问 Element's 的函数的数量。内部,使用上述示例和两个操作(检查液位和检查排放):

CarElement 访客
操作操作
休息 2 2
挡风玻璃雨刮器 2 2
轮子 2 1

关于design-patterns - 访问者模式和违反封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18470104/

相关文章:

java - 如何在胖客户端中设计身份验证以确保故障安全?

c# - 存储库模式以及如何管理实体之间的依赖关系

java - 如何在 Builder 设计模式中实现方法的条件可见性?

c++ - 隐式转换掩盖了重载的运算符。如何解决?

Java Architecture - 是否应该在构造函数中传递常用的类?

c++ - 装饰器模式的线程安全

HTML 模式阿拉伯字母

java - hibernate 基础知识

iphone - 可以有两个指定的初始化程序吗?

c# - 用于更改项目条例的自定义排序算法