行为型模型 访问者模式

行为型模型 访问者模式

抽象访问者(Visitor)角色:
        声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。
具体访问者(ConcreteVisitor)角色:
        实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象节点(Element)角色:
        声明一个接受操作,接受一个访问者对象作为一个参量。
具体节点(ConcreteElement)角色:
        实现了抽象元素所规定的接受操作。
结构对象(ObiectStructure)角色:
        有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。

适用于:
        两批人事物;随意的增加操作。相互解耦合。

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


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

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

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <list>

//客户去银行办理业务
//m个客户
//n个柜员

//将要 对象和要处理的操作分开,不同的柜员可以办理不同来访者的业务

// 前置声明
class Element;

// 访问者访问柜员
class Visitor
{
public:
    virtual void visit(Element * element) = 0;
    virtual ~Visitor() {}
};

// 柜员接受客户访问
class Element
{
public:
    virtual void accept(Visitor * v) = 0;
    virtual std::string getName() = 0;
    virtual ~Element() {}
};

// 柜员A员工
class EmployeeA: public Element
{
public:
    EmployeeA(std::string name)
    {
        m_name = name;
    }
    virtual void accept(Visitor * v) override
    {
        v->visit(this);
    }
    virtual std::string getName() override
    {
        return m_name;
    }

private:
    std::string m_name;
};

// 柜员B员工
class EmployeeB: public Element
{
public:
    EmployeeB(std::string name)
    {
        m_name = name;
    }
    virtual void accept(Visitor * v) override
    {
        v->visit(this);
    }
    virtual std::string getName() override
    {
        return m_name;
    }

private:
    std::string m_name;
};

class VisitorA: public Visitor
{
public:
    virtual void visit(Element * element) override
    {
        std::cout << "通过" << element->getName() << "做A业务" << std::endl;
    }
};

class VisitorB: public Visitor
{
public:
    virtual void visit(Element * element) override
    {
        std::cout << "通过" << element->getName() << "做B业务" << std::endl;
    }
};

// 柜员组组长
class Employees: public Element
{
public:
    Employees(std::string name)
    {
        m_list = new std::list<Element *>;
        m_name = name;
    }
    virtual void accept(Visitor * v) override
    {
        std::cout << m_name << "接受访问" << std::endl;
        for (std::list<Element *>::iterator it = m_list->begin(); it != m_list->end(); it++)
        {
            (*it)->accept(v);
        }
    }
    virtual std::string getName() override
    {
        return m_name;
    }
    void addElement(Element * e)
    {
        m_list->push_back(e);
    }
    void removeElement(Element * e)
    {
        m_list->remove(e);
    }
private:
    std::list<Element *> * m_list;
    std::string m_name;
};


void mytest()
{
    EmployeeA *eA = new EmployeeA("柜员A");
    EmployeeB *eB = new EmployeeB("柜员B");
    Employees *es = new Employees("柜员组组长");
    es->addElement(eA);
    es->addElement(eB);
    VisitorA *vA = new VisitorA();
    VisitorB *vB = new VisitorB();
    std::cout << "--------------" << std::endl;
    es->accept(vA);
    std::cout << "--------------" << std::endl;
    es->accept(vB);
    std::cout << "--------------" << std::endl;

    delete eA;
    eA = nullptr;
    delete eB;
    eB = nullptr;
    delete es;
    es = nullptr;
    delete vA;
    vA = nullptr;
    delete vB;
    vB = nullptr;


    return;
}

int main()
{
    mytest();

    system("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/lsgxeva/p/7783329.html