C++设计模式——访问者模式

访问者模式

在GOF的《设计模式:可复用面向对象软件的基础》一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。该模式的目的是要把处理从数据结构分离出来。访问者模式让增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。现在再来说说我之前经历过的那个项目。

是基于Windows Shell开发的一个项目,在一个容器中存储了很多的Shell Items,同时定义了对Items的操作,由于项目一直都在进行后期扩展,对Items的操作在后期都需要进行扩展的;而现在的做法是,定义一个操作类,该操作类中定义了一个集合,该集合存放Items,在该操作类中扩展对应的操作方法。现在想想如果使用访问者模式也是可以的,由于Items集合是固定的,当需要扩展集合的操作时,只需要添加对应的访问者即可。

UML类图

Visitor(访问者):为该对象结构中ConcreteElement的每一个类声明一个Visit操作。该操作的名字和特征标识了发送Visit请求给该访问者的那个类。这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
ConcreteVisitor(具体访问者):实现每个由Visitor声明的操作。每个操作实现本算法的一部分,而该算法片段乃是对应于结构中对象的类。ConcreteVisitor为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。
Element(元素):定义一个Accept操作,它以一个访问者为参数。
ConcreteElement(具体元素):实现Accept操作,该操作以一个访问者为参数。
ObjectStructure(对象结构):能够枚举它的元素,同时提供一个高层的接口以允许该访问者访问它的元素。

使用场合

  1. 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作;
  2. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中;
  3. 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作;
  4. 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

代码实现

  1 #include <iostream>
  2 #include <vector>
  3 using namespace std;
  4
  5 class ConcreteElementA;
  6 class ConcreteElementB;
  7
  8 class Visitor
  9 {
 10 public:
 11      virtual void VisitConcreteElementA(ConcreteElementA *pElementA) = 0;
 12      virtual void VisitConcreteElementB(ConcreteElementB *pElementB) = 0;
 13 };
 14
 15 class ConcreteVisitor1 : public Visitor
 16 {
 17 public:
 18      void VisitConcreteElementA(ConcreteElementA *pElementA);
 19      void VisitConcreteElementB(ConcreteElementB *pElementB);
 20 };
 21
 22 void ConcreteVisitor1::VisitConcreteElementA(ConcreteElementA *pElementA)
 23 {
 24      // 现在根据传进来的pElementA,可以对ConcreteElementA中的element进行操作
 25 }
 26
 27 void ConcreteVisitor1::VisitConcreteElementB(ConcreteElementB *pElementB)
 28 {
 29      // 现在根据传进来的pElementB,可以对ConcreteElementB中的element进行操作
 30 }
 31
 32 class ConcreteVisitor2 : public Visitor
 33 {
 34 public:
 35      void VisitConcreteElementA(ConcreteElementA *pElementA);
 36      void VisitConcreteElementB(ConcreteElementB *pElementB);
 37 };
 38
 39 void ConcreteVisitor2::VisitConcreteElementA(ConcreteElementA *pElementA)
 40 {
 41      // ...
 42 }
 43
 44 void ConcreteVisitor2::VisitConcreteElementB(ConcreteElementB *pElementB)
 45 {
 46      // ...
 47 }
 48
 49 // Element object
 50 class Element
 51 {
 52 public:
 53      virtual void Accept(Visitor *pVisitor) = 0;
 54 };
 55
 56 class ConcreteElementA : public Element
 57 {
 58 public:
 59      void Accept(Visitor *pVisitor);
 60 };
 61
 62 void ConcreteElementA::Accept(Visitor *pVisitor)
 63 {
 64      pVisitor->VisitConcreteElementA(this);
 65 }
 66
 67 class ConcreteElementB : public Element
 68 {
 69 public:
 70      void Accept(Visitor *pVisitor);
 71 };
 72
 73 void ConcreteElementB::Accept(Visitor *pVisitor)
 74 {
 75      pVisitor->VisitConcreteElementB(this);
 76 }
 77
 78 // ObjectStructure类,能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素
 79 class ObjectStructure
 80 {
 81 public:
 82      void Attach(Element *pElement);
 83      void Detach(Element *pElement);
 84      void Accept(Visitor *pVisitor);
 85
 86 private:
 87      vector<Element *> elements;
 88 };
 89
 90 void ObjectStructure::Attach(Element *pElement)
 91 {
 92      elements.push_back(pElement);
 93 }
 94
 95 void ObjectStructure::Detach(Element *pElement)
 96 {
 97      vector<Element *>::iterator it = find(elements.begin(), elements.end(), pElement);
 98      if (it != elements.end())
 99      {
100           elements.erase(it);
101      }
102 }
103
104 void ObjectStructure::Accept(Visitor *pVisitor)
105 {
106      // 为每一个element设置visitor,进行对应的操作
107      for (vector<Element *>::const_iterator it = elements.begin(); it != elements.end(); ++it)
108      {
109           (*it)->Accept(pVisitor);
110      }
111 }
112
113 int main()
114 {
115      ObjectStructure *pObject = new ObjectStructure;
116
117      ConcreteElementA *pElementA = new ConcreteElementA;
118      ConcreteElementB *pElementB = new ConcreteElementB;
119
120      pObject->Attach(pElementA);
121      pObject->Attach(pElementB);
122
123      ConcreteVisitor1 *pVisitor1 = new ConcreteVisitor1;
124      ConcreteVisitor2 *pVisitor2 = new ConcreteVisitor2;
125
126      pObject->Accept(pVisitor1);
127      pObject->Accept(pVisitor2);
128
129      if (pVisitor2) delete pVisitor2;
130      if (pVisitor1) delete pVisitor1;
131      if (pElementB) delete pElementB;
132      if (pElementA) delete pElementA;
133      if (pObject) delete pObject;
134
135      return 0;
136 }

总结

访问者模式的基本思想如下:首先拥有一个由许多对象构成的对象结构,就是上面代码中的ObjectStructure,这些对象的类都拥有一个Accept方法用来接受访问者对象;访问者是一个接口,它拥有一个Visit方法,这个方法对访问到的对象结构中不同类型的元素做出不同的操作;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施Accept方法,在每一个元素的Accept方法中回调访问者的Visit方法,从而使访问者得以处理对象结构的每一个元素。我们就可以针对对象结构设计不同的访问者类来完成不同的操作。

设计模式中经常说的一句话是:发现变化并封装之。是否采用访问者模式,就要看“变化”是什么。访问者模式中,“变化”是具体访问者,其次是对象结构;但是,如果具体元素也会发生改变,就万万不能使用访问者模式,因为这样“牵一发而动全身”,后期的维护性就太差了。

原文地址:https://www.cnblogs.com/ring1992/p/9593591.html

时间: 2024-10-14 06:46:22

C++设计模式——访问者模式的相关文章

.NET设计模式访问者模式

一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它.2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口.3.Element 定义一个接受访问操作(accept

[我的设计模式] 访问者模式

访问者模式(Visitor Pattern)是GoF提出的23种设计模式中的一种,属于行为模式. 定义(源于GoF<Design Pattern>):表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 从定义可以看出结构对象是使用访问者模式必备条件,而且这个结构对象必须存在遍历自身各个对象的方法. 应用场景 用户访问博客.[我的设计模式] 访问者模式

【C#设计模式-访问者模式】

一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它. 2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口. 3.Element 定义一个接受访问操作(acce

最复杂的设计模式---访问者模式

今天,我们一起来探讨最后一个.最复杂的设计模式 访问者模式:它表示一个作用于某个对象结构中的各个元素的操作.它使你可以在不改变个元素的类前提下,定义作用于这些元素的新操作.这个地方要注意:1.需要有个对象结构类用于存储循环遍历的方法的方式:2.访问者模式是对元素的操作:3.可以任意添加对这些元素的新操作.确实有点复杂,我们先看看其结构图: 代码部分: Visitor类抽象声明了对各种类型元素的访问方法: abstract class Visitor { public abstract void

C#设计模式-访问者模式

一.访问者模式介绍 1.1 访问者模式的定义 表示一个作用于某对象结构中的各个元素的操作.它使你可以在不改变各个元素的类的前提下定义作用于这些元素的新操作. 1.2 访问者模式的结构图 具体的访问者模式结构图如下所示. 这里需要明确一点:访问者模式中具体访问者的数目和具体节点的数目没有任何关系.从访问者的结构图可以看出,访问者模式涉及以下几类角色. 抽象访问者角色(Vistor):声明一个活多个访问操作,使得所有具体访问者必须实现的接口. 具体访问者角色(ConcreteVistor):实现抽象

小菜学设计模式——访问者模式

背景 最后一个设计模式,也是<大话设计模式>公认最难的设计模式,当然不是理解上困难,我觉得应该是使用上困难,这个设计模式虽然具有非常良好的扩展能力,但却需要类的结构早早定义清晰,试想,需求时刻变化,你的类可以稳定吗? 1.使用意图 容易扩展,满足开发封闭原则 2.生活实例 男人和女人的状态,把ConcreteElmentA看成男人,把ConcreteElementB看成女人,那么,所有的Visitor实例就是成功状态.失败状态.结婚状态.升职状态等.把这些状态放在客户端的集合中维护,一旦需要,

PHP设计模式——访问者模式

声明:本系列博客参考资料<大话设计模式>,作者程杰. 访问者模式表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. UML类图: 角色: 1.抽象访问者(State):为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它. 2.具体访问者(Success):实现访问者声明的接口. 3.抽象元素(Person):定义一个接受访问操

深入浅出设计模式——访问者模式(Visitor Pattern)

模式动机 对于系统中的某些对象,它们存储在同一个集合中,且具有不同的类型,而且对于该集合中的对象,可以接受一类称为访问者的对象来访问,而且不同的访问者其访问方式有所不同,访问者模式为解决这类问题而诞生.在实际使用时,对同一集合对象的操作并不是唯一的,对相同的元素对象可能存在多种不同的操作方式.而且这些操作方式并不稳定,可能还需要增加新的操作,以满足新的业务需求.此时,访问者模式就是一个值得考虑的解决方案.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这

iOS设计模式---访问者模式

一个简单的Car模型,含有1台Engine.4个Wheel,使用访问者模式添加对Car的升级与维修操作. 定义Engine类: // //  NimoEngine.h //  VisitorDemo // //  Created by fu zheng on 15/8/12. //  Copyright (c) 2015年 FuZheng. All rights reserved. // #import <Foundation/Foundation.h> #import "NimoC