1. 情景与意图
冰柜我们存放了很多食物,对于妈妈来说,打开冰柜主要是拿蔬菜,肉食做饭,对于孩子来说主要是拿冰淇淋,饮品。
在日常的开发中,肯定有一些类是属于数据结构相关的,比如设计数据存储的model。但是该类中的数据种类很多,针对不同的访问者,我们应该是呈现不同数据,不应该呈现所有的数据,也就是做隔离。
在我们日常的开发中,如何实现这种针对不同访问者的特性进行隔离呢?——访问者模式。
2. 访问者模式
表示一个作用于某对象结构中的各元素的操作,使得可以在不改变各元素的前提下定义新的操作。
这里的操作,不是这个类的对象的行为,而是指的是访问,将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中,类的职责更加清晰,符合单一职责原则。
下面我们用代码来看看。
3. 冰柜
首先,访问者模式的前提,类的结构是固定的,如果不是固定的,后面入股改变的类的层次结构,就需要再次更改访问者的类。比如一个类表示的公司的账目,已经提供了收入和支出。那么这就是固定的,如果后面还要税务的操作,那么就要改变这个类,这会导致后面的访问者类也要跟着改。
我们先定义好冰柜。
class DPVisitor;
class DPFreezer {
public:
virtual void accept(DPVisitor& visitor) = 0;
};
/*
访问者模式的前提就是类的结构是确定的,即就是类中对象是确定的,比如也就是说冰箱的层级是确定的
看看后面的访问者就知道了。
*/
class DPFreshkeeping : public DPFreezer {
public:
virtual void accept(DPVisitor& visitor);
};
class DPRefrigeration : public DPFreezer {
public:
virtual void accept(DPVisitor& visitor);
};
然后我们定义访问者。
class DPFreezer;
class DPVisitor{
public:
virtual void visitorFreshkeeping(DPFreezer& freezer) = 0;
virtual void visitorRefrigeration(DPFreezer& freezer) = 0;
// 比如冰箱类又新增了软冻层,那么这里的访问者类也要跟着改
};
class DPVisitorMom : public DPVisitor {
public:
virtual void visitorFreshkeeping(DPFreezer& freezer);
virtual void visitorRefrigeration(DPFreezer& freezer);
};
class DPVisitorKids : public DPVisitor {
public:
virtual void visitorFreshkeeping(DPFreezer& freezer);
virtual void visitorRefrigeration(DPFreezer& freezer);
};
下面看看核心的实现。
void DPVisitorMom::visitorFreshkeeping(DPFreezer& freezer) {
// 添加的操作
printf("妈妈访问了保鲜层,展示蔬菜\n");
}
void DPVisitorMom::visitorRefrigeration(DPFreezer& freezer) {
// 添加的操作
printf("妈妈访问了冷藏层,展示肉食、饺子\n");
}
void DPVisitorKids::visitorFreshkeeping(DPFreezer& freezer) {
// 添加的操作
printf("孩子访问了保鲜层,展示牛奶,果汁\n");
}
void DPVisitorKids::visitorRefrigeration(DPFreezer& freezer) {
// 添加的操作
printf("孩子访问了冷藏层,展示冰淇淋\n");
}
// 如果要继续添加操作
// 则创建visitor即可
直接看调用吧
int main() {
DPFreezer* freshkeeping = new DPFreshkeeping();
DPFreezer* refrigeration = new DPRefrigeration();
DPVisitor* mom = new DPVisitorMom();
DPVisitor* kid = new DPVisitorKids();
freshkeeping->accept(*mom);
freshkeeping->accept(*kid);
refrigeration->accept(*mom);
refrigeration->accept(*kid);
return 0;
}
4. 大总结
好了,又到了大总结的时候了,没有阅读前面的命令模式的同学,欢迎阅读:【命令模式】。
这两个模式都属于‘行为变化’模式,主要解决的是:对象本身行为的变化,会导致对象本身的变化。简单的说,添加新的行为,会改变原有 比如之前的命令模式博文中,添加新的命令,如果没有使用命令模式会改变command()方法。这两种模式就是为了应对这种变化,抑制变化的扩大,维持稳定。
C++实现访问者模式源码:【访问者模式C++源码】