访问者模式是23中GoF模式的一种,属于行为型设计模式,它让你定义一个类的新操作而无需改变它操作的这些成员类。
现实生活中,收银员收银计费就属于访问者模式。比如,当顾客在超市选择了香蕉、面包、酒放在购物车中,然后到收银台交钱。那么收银员就是一个访问者,他要访问购物车内顾客选择的每一种商品,购物车就作为对象结构类(ObjectStructure),它里面的商品都需要一个accept操作,接收收银员的检查计价。各种商品的计价方法不一样,比如香蕉需要称重计价,面包扫描条形码计价,买酒还有年龄限制等。具体收银员要定义好访问各个商品的方法。我们根据该例子来说明访问者模式中类和对象的关系:
Vistor(抽象访问者类) : 为对象结构类中每一个ConcreteElement类声明一个visit操作;
ConcreteVistor(具体访问者类):实现每个由visitor声明的操作,比如本例子中的收银员类(Cashier)
Element(抽象元素类):定义一个accept操作,它以一个访问者为参数。
ConcreteElement(具体元素类):实现accept操作,比如本例子中的商品类(Goods)。
ObjectorStructure(对象结构类):提供一个高层的接口允许访问者访问其元素,比如本例中的购物车类(Shopping_cart)。
用C++简单实现上面描述的收银员收银计费的例子:
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Element;
class Vistor //访问者抽象类
{
public:
virtual void visit (const string &name) = 0;
};
class Cashier : public Vistor
{
public:
void visit (const string &name)
{
if (name == "香蕉")
{
cout << "香蕉是称重计费的" << endl;
}
else if (name == "面包")
{
cout << "面包扫条形码计费的" << endl;
}
else
{
cout << "想买酒,先报年龄" << endl;
}
}
};
class Element
{
public:
virtual void accept (Vistor *v) = 0;
};
class Goods : public Element //各种商品抽象
{
public:
Goods (string n, double p = 0.0, int c = 0)
: name (n), unit_price (p), count (c)
{}
string getname()
{
return name;
}
void accept (Vistor *v)
{
v -> visit (this -> name);
}
private:
string name; //商品名称
double unit_price; //单价
int count; //数量
};
class Shopping_cart
{
public:
Shopping_cart ()
{
goods_list.clear();
}
void add_goods (Goods *em) //商品的添加
{
goods_list.push_back(em);
}
void del_goods (Goods *em) //商品的删除
{
list<Goods *> :: iterator it = goods_list.begin();
while (it != goods_list.end())
{
if (((*it) -> getname()) == em -> getname())
{
goods_list.erase (it);
break;
}
++it;
}
}
void goods_accept (Vistor *v) //购物车中的所有商品接受计费
{
list<Goods *> :: iterator it = goods_list.begin();
while (it != goods_list.end())
{
(*it) -> accept (v);
++ it;
}
}
private:
list<Goods *> goods_list;
};
int main()
{
Shopping_cart *cart = new Shopping_cart();
Goods *banana = new Goods("香蕉", 3.5, 2);
Goods *bread = new Goods ("面包", 7.5, 1);
Goods *wine = new Goods ("酒", 129.9, 1);
cart -> add_goods (banana);
cart -> add_goods (bread);
cart -> add_goods (wine);
Vistor *v1 = new Cashier();
cart -> goods_accept (v1);
cout << endl << endl;
cart -> del_goods (bread);
cart -> goods_accept(v1);
cout << endl;
delete v1;
delete banana;
delete bread;
delete wine;
delete cart;
return 0;
}
运行结果: