使用Visitor模式优雅地处理类层次操作

需积分: 10 1 下载量 13 浏览量 更新于2024-10-21 收藏 64KB DOC 举报
"本文档探讨了在软件设计中遇到的一个问题,即如何在已有的类层次结构中添加新的功能而不破坏原有代码的封装性。作者提到了Visitor模式,并通过一个具体的例子展示了如何使用该模式来避免使用Runtime Type Information (RTTI) 和条件语句来实现多态行为。" 在面向对象编程中,Visitor模式是一种行为设计模式,主要用于在不修改已有类层次结构的情况下,向对象结构添加新的操作。这个模式的核心思想是将数据结构与数据操作分离,使得我们可以独立地扩展对象结构中的元素类和访问者类。 在提供的示例中,作者面临的问题是在`Personnel`类层次(包括`Officer`, `Captain` 和 `First Officer`)中添加一个特定于类的操作,而不能直接修改这些类。通常,我们可以通过在基类中添加虚拟函数来实现多态行为,但这在本例中是不可能的。作者尝试使用RTTI(运行时类型信息)来识别对象的具体类型并执行相应的操作,但这种方法不被公司的编码标准接受,因为它会降低代码的灵活性和可维护性。 这时,Visitor模式提供了另一种解决方案。在Visitor模式中,我们创建一个`Visitor`接口,这个接口定义了一系列针对类层次结构中各个元素的操作。然后,每个类(如`Personnel`, `Officer`, `Captain`, 和 `First Officer`)都增加一个`Accept`方法,用来接受一个`Visitor`对象的访问。`Accept`方法的实现由具体类完成,它会调用相应的`Visit`方法,该方法定义在`Visitor`接口中,这样就可以在不修改原有类结构的前提下,为每个类添加新的行为。 例如,可以创建一个`SpecificActionVisitor`类,它实现了`Visitor`接口,并且有针对`Captain`和`First Officer`的`Visit`方法: ```cpp class SpecificActionVisitor : public Visitor { public: void Visit(Captain& captain) override { // 对Captain执行特定操作 } void Visit(First& firstOfficer) override { // 对First Officer执行特定操作 } }; ``` 接着,`Personnel`类的每个子类(`Officer`, `Captain`, `First`)都会包含一个`Accept`方法: ```cpp class Personnel { public: virtual void Accept(Visitor& visitor) = 0; }; class Officer : public Personnel { public: void Accept(Visitor& visitor) override { visitor.Visit(*this); } // ... }; class Captain : public Officer { // ... }; class First : public Officer { // ... }; ``` 现在,当需要对`Captain`或`First Officer`执行特定操作时,我们不再需要使用RTTI,而是创建一个`SpecificActionVisitor`对象,并将其传递给对象的`Accept`方法: ```cpp SpecificActionVisitor visitor; Captain k; First s; k.Accept(visitor); s.Accept(visitor); ``` 通过这种方式,我们实现了在不修改原始类层次结构的基础上添加新功能的目标,同时也遵循了公司的编码标准,避免了对RTTI的依赖。Visitor模式的优点在于它保持了类结构的封闭性,使得添加新操作变得容易,同时使得代码更加灵活和可扩展。