23种设计模式C++源码与UML实现--访问者模式

本文介绍了访问者模式的基本概念,包括抽象访问者、具体访问者、抽象节点和具体节点,以及结构对象的作用。通过公园管理案例展示如何利用访问者模式实现行为解耦和行为扩展。优缺点和适用场景也被详细阐述,强调了其在软件设计中的开闭原则实践。
摘要由CSDN通过智能技术生成
访问者模式

Vistor模式也叫访问者模式,是行为模式之一,它分离对象的数据和行为,使用Vistor模式,可以不修改已有类的情况下,增加新的操作角色和职责。

在这里插入图片描述

抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。

具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。

抽象节点(Element)角色:声明一个接受操作,接受一个访问者对象作为一个参量。

具体节点(ConcreteElement)角色:实现了抽象元素所规定的接受操作。

结构对象(ObiectStructure)角色:有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。

适用于

把数据结构 和 作用于数据结构上的操作 进行解耦合; 适用于数据结构比较稳定的场合

访问者模式总结

访问者模式优点是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
那访问者模式的缺点是是增加新的数据结构变得困难了

优缺点

访问者模式有如下的优点:

  1. 访问者模式使得增加新的操作变得很容易。如果一些操作依赖于一个复杂的结构对象
    的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味
    着增加一个新的访问者类,因此,变得很容易。
  2. 访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
  3. 访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只
    能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问
    者模式可以做到这一点。
  4. 积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过
    程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系
    统维护的优点。

访问者的缺点:

  1. 增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增
    加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
  2. 破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了
    一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的
    访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态
    不再存储在节点对象中,这也是破坏封装的。

案例需求:

比如有一个公园,有一到多个不同的组成部分;该公园存在多个访问者:清洁工 A 负责打扫公园的 A 部分,清洁工 B 负责打扫公园的 B 部分,公园的管理者负责检点各项事务是否完成,上级领导可以视察公园等等。也就是说,对于同一个公园,不同的访问者有不同的行为操作,而且访问者的种类也可能需要根据时间的推移而变化(行为的扩展性)。
根据软件设计的开闭原则(对修改关闭,对扩展开放),实现需求。

//
// Created by andrew on 2020/11/28.
//
#include <iostream>
#include <list>

using namespace std;

class ParkElement;

class Visitor{
public:
    virtual ~Visitor() = default;
    virtual void visit(ParkElement *parkElement) = 0;
};

class ParkElement{
public:
    virtual ~ParkElement() = default;
    virtual void accept(Visitor *visitor) = 0;
};

class ParkA : public ParkElement{
public:
    void accept(Visitor *v) override{
        // 公园接收访问者, 让访问者操作
        v->visit(this);
    }
};

class ParkB : public ParkElement{
public:
    void accept(Visitor *v) override{
        v->visit(this);
    }
};

// 整个公园
class Park : ParkElement {
public:
    Park(){
        m_list.clear();
    }

    void setParkElement(ParkElement *pe){
        m_list.push_back(pe);
    }

    void accept(Visitor *v) override{
        for(auto it=m_list.begin();it!=m_list.end(); it++)
        {
            (*it)->accept(v);
        }
    }

private:
    list<ParkElement *>m_list;
};

class VisitorA : public Visitor{
    void visit(ParkElement *parkElement) override {
        cout << "part A is clear" << endl;
    }
};

class VisitorB : public Visitor {
public:
    void visit(ParkElement *parkElement) override{
        cout << "part B is clear" << endl;
    }
};

class ManagerVisitor : public Visitor {
public:
    void visit(ParkElement * parkElement) override {
        cout << "visit all part" << endl;
    }
};

void PartVisitor() {
    Visitor *vA = new VisitorA;
    Visitor *vB = new VisitorB;

    auto *parkA = new ParkA;
    auto *parkB = new ParkB;

    parkA->accept(vA);
    parkB->accept(vB);

    delete vA;
    delete vB;
    delete parkB;
    delete parkA;
}

void ManagerVisit() {
    Visitor *vManager = new ManagerVisitor;
    Park *park = new Park;

    ParkElement *parkA = new ParkA;
    ParkElement *parkB = new ParkB;

    park->setParkElement(parkA);
    park->setParkElement(parkB);

//    整个公园接受管理员的访问
    park->accept(vManager);

    delete parkA;
    delete parkB;
    delete park;
    delete vManager;
}

int main(int argc, char* argv[]){

    PartVisitor();
    ManagerVisit();

    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Achou.Wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值