访问者模式
简介
: 类的内部结构不变的情况下,不同的访问者访问这个对象都会呈现出不同的处理方式。
人话
: 其实就是为了解决类结构不变但操作处理逻辑易变的问题,把对数据的操作都封装到访问者类中,
我们只需要调用不同的访问者,而无需改变改变结构类,实现了。
举个理发店的例子
理发店:
用户分为: 普通用户 和 会员用户
toney老师分为: 技师, 总监, 店长
不通的用户有不通的老师正常思路:
一个客户类, 一个理发师类
然后理发师类中针对不通的客户进行收费问题:
我们不想动理发师类, 因为在理发店的这个环境下, 理发师类肯定是比消费者类复杂很多的, 所以我们
使用访问者模式, 将数据的处理逻辑放到访问者里面, 这样理发师就不用经常修改了访问者模式:
访问者类: 客户类, 实现visit方法
被访问者类: 理发师类, 实现accept方法
`代码``如下所示
class ToneyTeacher;class Customer
{
public:string name;Customer(string n) : name(n) {};virtual double visit(ToneyTeacher* t) =0;
};class ToneyTeacher
{
private:int price = 0;string name;
public:ToneyTeacher(string n, int p) :name(n), price(p) {};int get_price() { return price; };ToneyTeacher(int p) : price(p) {};void accept(Customer* c);
};class NormalCustomer : public Customer
{
public:NormalCustomer(string name) : Customer(name) {};double visit(ToneyTeacher* t) override{return 1 * t->get_price();}
};class VIPCustomer : public Customer
{
public:VIPCustomer(string name) : Customer(name) {};double visit(ToneyTeacher* t) override{return 0.8 * t->get_price();}
};void ToneyTeacher::accept(Customer* c)
{cout << name << "原价: " << price << ", 收 " << c->name << " 费用: " << c->visit(this) << endl;
}int main()
{VIPCustomer* vip_c = new VIPCustomer("vip客户");NormalCustomer* normal_c = new NormalCustomer("普通客户");ToneyTeacher* t1 = new ToneyTeacher("技师", 10);ToneyTeacher* t2 = new ToneyTeacher("总监", 20);ToneyTeacher* t3 = new ToneyTeacher("店长", 30);t1->accept(vip_c);t2->accept(vip_c);t3->accept(vip_c);t1->accept(normal_c);t2->accept(normal_c);t3->accept(normal_c);return 0;
}
执行结果