开发者社区> 潘志闻> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

C++访问者模式

简介: 简述 访问者模式(Visitor Pattern)表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
+关注继续查看

简述

访问者模式(Visitor Pattern)表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820

模式结构

UML 结构图:

Visitor Pattern

  • Vistor(访问者):为对象结构中每一个 ConcreteElement 声明一个 visit() 操作,从这个操作的名称或参数类型可以清楚知道需要访问的具体元素的类型。
  • ConcreteVisitor(具体访问者):实现每个由 Visitor 声明的操作。
  • Element(元素):定义一个 accept() 操作,它通常以一个 Vistor 作为参数。
  • ConcreteElement(具体元素):实现 accept() 操作,通过调用 Visitor 的 visit() 方法来实现对元素的访问。
  • ObjectStructure(对象结构):能够枚举它的元素,同时提供一个高层的接口,以允许访问者访问它的元素。

优缺点

优点:

  • 增加新的访问操作很方便。使用访问者模式,增加新的访问操作就意味着增加一个新的具体访问者类,实现简单,无须修改源代码,符合“开闭原则”。
  • 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中。类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。
  • 让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。

缺点:

  • 增加新的元素类困难。每增加一个新的元素类都意味着要在访问者中增加一个新的操作,并在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”的要求。
  • 破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。

适用场景

  • 一个对象结构包含多个类型的对象,希望对这些对象实施一些依赖其具体类型的操作。在访问者中针对每一种具体的类型都提供了一个访问操作,不同类型的对象可以有不同的访问操作。
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。访问者模式使得我们可以将相关的访问操作集中起来定义在访问者类中,对象结构可以被多个不同的访问者类所使用,将对象本身与对象的访问操作分离。
  • 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

案例分析

古城西安 - 访问记

xian

西安历史悠久,有着 7000 多年文明史、3100 多年建城史、1100 多年的建都史,是中华文明和中华民族重要发祥地,丝绸之路的起点。。。西安与雅典、罗马、开罗并称为世界四大古都。

二十年中国看深圳,一百年中国看上海,一千年中国看北京,而五千年中国则看西安。

作为中国最佳的旅游胜地,西安有很多著名的景点:秦始皇兵马俑、大雁塔、大唐芙蓉园、华清池、钟/鼓楼、骊山、古城墙、历史博物馆。。。

在访问西安时,访问者会参观各个景点。对于景点来说,无论访问者是谁,它们都是不变的。而作为访问者,不同角色的访问方式也不尽相同,游客只负责旅游 - 吃喝玩乐,而清洁工则需要打扫卫生、清理垃圾。

这里,游客和清洁工是具体访问者,兵马俑、钟楼等景点是具体元素,西安这座城市是结构对象。

代码实现

创建访问者

访问者需要为每个景点都提供一个访问方法:

// visitor.h
#ifndef VISITOR_H
#define VISITOR_H

class BellTower;
class TerracottaWarriors;

// 访问者
class IVisitor
{
public:
    virtual ~IVisitor() {}
    virtual void Visit(BellTower *) = 0;
    virtual void Visit(TerracottaWarriors *) = 0;
};

#endif // VISITOR_H

创建具体访问者

具体访问者有两种 - 游客、清洁工,它们分别实现了不同的访问操作(游客只管吃喝玩乐,清洁工负责清理垃圾):

// concrete_visitor.h
#ifndef CONCRETE_VISITOR_H
#define CONCRETE_VISITOR_H

#include "visitor.h"
#include "concrete_element.h"

// 游客
class Tourist : public IVisitor
{
public:
    virtual void Visit(BellTower *) override {
        std::cout << "I'm visiting the Bell Tower!" << std::endl;
    }

    virtual void Visit(TerracottaWarriors *) override {
        std::cout << "I'm visiting the Terracotta Warriors!" << std::endl;
    }
};

// 清洁工
class Cleaner : public IVisitor
{
public:
    virtual void Visit(BellTower *) override {
        std::cout << "I'm cleaning up the garbage of Bell Tower!" << std::endl;
    }

    virtual void Visit(TerracottaWarriors *) override {
        std::cout << "I'm cleaning up the garbage of Terracotta Warriors!" << std::endl;
    }
};

#endif // CONCRETE_VISITOR_H

创建元素

景点中定义了一个 Accept() 接口,用于接受访问者的访问:

// element.h
#ifndef ELEMENT_H
#define ELEMENT_H

class IVisitor;

// 地方
class IPlace
{
public:
    virtual ~IPlace() {}
    virtual void Accept(IVisitor *visitor) = 0;
};

#endif // ELEMENT_H

创建具体元素

具体元素有两个 - 钟楼、兵马俑,它们实现了 Accept() 方法:

// concrete_element.h
#ifndef CONCRETE_ELEMENT_H
#define CONCRETE_ELEMENT_H

#include "element.h"
#include "visitor.h"
#include <iostream>

// 钟楼
class BellTower : public IPlace
{
public:
    virtual void Accept(IVisitor *visitor) override {
        std::cout << "Bell Tower is accepting visitor." << std::endl;
        visitor->Visit(this);
    }
};

// 兵马俑
class TerracottaWarriors : public IPlace
{
public:
    virtual void Accept(IVisitor *visitor) override {
        std::cout << "Terracotta Warriors is accepting visitor." << std::endl;
        visitor->Visit(this);
    }
};

#endif // CONCRETE_ELEMENT_H

注意: 在 Accept() 方法中,通过调用 Visitor 的 visit() 方法(以当前对象为参数)来实现对景点的访问。

创建对象结构

添加景点,并为每一个景点添加访问者:

// object_structure.h
#ifndef OBJECT_STRUCTURE_H
#define OBJECT_STRUCTURE_H

#include "element.h"
#include <list>

// 城市(西安)
class City
{
public:
    void Attach(IPlace *place) {
        m_places.push_back(place);
    }

    void Detach(IPlace *place) {
        m_places.remove(place);
    }

    void Accept(IVisitor *visitor) {
        // 为每一个 element 设置 visitor,进行对应的操作
        for (std::list<IPlace*>::iterator it = m_places.begin(); it != m_places.end(); ++it) {
            (*it)->Accept(visitor);
        }
    }

private:
    std::list<IPlace *> m_places;
};

#endif // OBJECT_STRUCTURE_H

创建客户端

欢迎来到古城西安,开始访问之旅吧:

// main.cpp
#include "concrete_visitor.h"
#include "object_structure.h"

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
#endif

int main()
{
    City *city = new City();

    // 景点 - 钟楼、兵马俑
    IPlace *bellTower = new BellTower();
    IPlace *warriors = new TerracottaWarriors();

    // 访问者 - 游客、清洁工
    IVisitor *tourist = new Tourist();
    IVisitor *cleaner = new Cleaner();

    // 添加景点
    city->Attach(bellTower);
    city->Attach(warriors);

    // 接受访问
    city->Accept(tourist);
    city->Accept(cleaner);

    SAFE_DELETE(cleaner);
    SAFE_DELETE(tourist);
    SAFE_DELETE(warriors);
    SAFE_DELETE(bellTower);
    SAFE_DELETE(city);

    getchar();

    return 0;
}

输出如下:

Bell Tower is accepting visitor.
I’m visiting the Bell Tower!
Terracotta Warriors is accepting visitor.
I’m visiting the Terracotta Warriors!
Bell Tower is accepting visitor.
I’m cleaning up the garbage of Bell Tower!
Terracotta Warriors is accepting visitor.
I’m cleaning up the garbage of Terracotta Warriors!

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Java设计模式 ->访问者模式
Java设计模式 ->访问者模式
0 0
我学会了,访问者模式
访问者模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
0 0
java设计模式之访问者模式
写这篇文章之前,我也看了十几篇网络大牛写的访问者设计模式的文章,都说这个访问者模式是最复杂的一个,但是我觉得跟其他的设计模式并没有太多的不同,因此自己整理了一下,相信大多数人都能看懂。
0 0
观察者模式和访问者模式(1)
观察者模式和访问者模式(1)
0 0
观察者模式和访问者模式(3)
观察者模式和访问者模式(3)
0 0
观察者模式和访问者模式(2)
观察者模式和访问者模式(2)
0 0
适配器模式之访问者模式
设计模式目录 http://blog.csdn.net/fenglailea/article/details/52733435 风.fox 访问者模式 封装一些作用于某种数据结构中的各个元素的操作,他可以在不改变数据结构的前提下定义作用于这些元素的新的操作 通用类图 组成 抽象访问者 Vistor 抽象接口或类,声明访问者可以访问那些元素,具体到程
852 0
9.访问者模式
1访问者模式的核心内容是: A:父类中存储一个作为关键字的变量。 B:子类根据这个关键的不同做不同的操作。 C:在访问的时候不用关心具体的内部实现方式,通过调用得出结论接口就可以得出结论。 2访问者模式的作用:送多个妹子花时,通过访问者模式实现根据特点做不同的配对。 3访问者模式具体描述 访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之
1010 0
+关注
潘志闻
互联网挖掘者
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载