访问器 -

本文详细介绍了访问者模式,如何通过访问者接口隔离数据结构和操作,并通过实例展示了如何在C++中实现。该模式有助于保持数据结构的稳定和操作的灵活性,遵循单一职责原则,但需要注意遵循迪米特原则和依赖倒置原则。
摘要由CSDN通过智能技术生成

在访问者模式中,我们使用一个访问这类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式俗语行为型模式。根据模式,元素对象以接受访问者对象,这样访问者对象可以处理元素对象上的操作。

1. 介绍

意图:主要将数据结构与数据操作分离。

主要解决:稳定的数据结构和易变的操作耦合问题。

何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类,使用访问者模式将这些类封装到类中。

如何解决:在被访问的类里面加一个对外提供接待访问者的接口。

关键代码:再数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

应用实例:您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。

优点:1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。

缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

2. 实例

2.1. C++实现

#include <iostream>
#include <string>
#include <memory>

class element; 
class visitor
{
public:
	virtual ~visitor(void){}
	virtual void visitor_element_fushi(element *elm) = 0;
	virtual void visitor_element_gougou(element *elm) = 0;
	virtual void visitor_element_siyao(element *elm) = 0;
};
class element 
{
public:  
	virtual ~element(){}
	virtual void accept(visitor* vis) = 0; 
};
//腐蚀
class fushi : public element
{
public:
	virtual void accept(visitor* vis)
	{
		vis->visitor_element_fushi(this);
	}
};
//钩子
class gougou : public element
{
public:
	virtual void accept(visitor* vis)
	{
		vis->visitor_element_gougou(this);
	}
};
//撕咬
class siyao : public element
{
public:
	virtual void accept(visitor* vis)
	{
		vis->visitor_element_siyao(this);
	}
};

class display_visitor : public visitor
{
public:
	virtual void visitor_element_fushi(element *elm)
	{
		std::cout << "visitor_element_fushi .." << std::endl;
	}
	virtual void visitor_element_gougou(element *elm)
	{
		std::cout << "visitor_element_gougou .." << std::endl;
	}
	virtual void visitor_element_siyao(element *elm)
	{
		std::cout << "visitor_element_siyao .." << std::endl;
	}
};
///
int main()
{
	std::cout << "start-up .." << std::endl;
	
	display_visitor dv;
	gougou gg;
	gg.accept(&dv);
	
	std::cout << "done .." << std::endl;
    return 0;
}

3. 实例2

实例2:

概述:

我们去银行柜台办业务,一般情况下会开几个个人业务柜台的,你去其中任何一个柜台办理都是可以的。我们的访问者模式可以很好付诸在这个场景中:对于银行柜 台来说,他们是不用变化的,就是说今天和明天提供个人业务的柜台是不需要有变化的。而我们作为访问者,今天来银行可能是取消费流水,明天来银行可能是去办 理手机银行业务,这些是我们访问者的操作,一直是在变化的。

UML:

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

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

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

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

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

#include <iostream>
#include <string>
#include <list>
using namespace std;

class Element;

class Visitor
{
public:
    virtual void Visit( Element *element ){};
};

// "Element"
class Element
{
public:
    // Methods
    virtual void Accept( Visitor *visitor ){};
};


// "ConcreteElement"
class Employee : public Element
{
public:
    string name;
    double income;
    int vacationDays;

public :
    Employee( string name, double income,
        int vacationDays )
    {
        this->name = name;
        this->income = income;
        this->vacationDays = vacationDays;
    }

    void Accept( Visitor *visitor )
    {
        visitor->Visit( this );
    }
};

class IncomeVisitor : public Visitor
{
public:    
    void Visit( Element *element )
    {
        Employee *employee = ((Employee*)element);
        employee->income *= 1.10;
        cout<<employee->name<<" 's new income: " <<employee->income<<endl;

    }
};

class VacationVisitor : public Visitor
{
public :
    void Visit( Element *element )
    {
        Employee *employee = ((Employee*)element);
        // Provide 3 extra vacation days
        employee->vacationDays += 3;        
        cout<<employee->name<<" 's new vacation days: " <<employee->income<<endl;
    }
};

// "ObjectStructure"
class Employees
{    
private :
    list< Employee*> employees;

public :

    void Attach( Employee *employee )
    {        
        employees.push_back(employee);        
    }

    void Detach( Employee *employee )
    {
        employees.remove(employee);        
    }

    void Accept( Visitor *visitor )
    {        
        for (std::list<Employee*>::iterator it=employees.begin(); it != employees.end(); ++it)
            (*it)->Accept(visitor);
    }
};

void main( )
{
    Employees *e = new Employees();
    e->Attach( new Employee( "Tom", 25000.0, 14 ) );
    e->Attach( new Employee( "Thomas", 35000.0, 16 ) );
    e->Attach( new Employee( "Roy", 45000.0, 21 ) );

    // Create two visitors
    IncomeVisitor *v1 = new IncomeVisitor();
    VacationVisitor *v2 = new VacationVisitor();

    // Employees are visited
    e->Accept( v1 );
    e->Accept( v2 );
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值