文章目录
背景介绍
这里有一个 Human ,和所有人类一样,这个 Human 同样要解决他的温饱问题:
访问者模式解决的就是在 Food 结构稳定的前提下,需要访问 Food 及其子类。
问题出现
Human 刚开始时也像大多数人吃东西一样,吃 Meat 有 吃 Meat 的吃法,吃 Vegetable 有吃 Vegetable 的吃法:
void Human::Eat(Food* food) {
if ((Meat * m = dynamic_cast<Meat *>(food)_!=NULL) {
//human 吃 m
m->MeatFunction();
} else if ((Vegetable * v = dynamic_cast<Vegetable *>(food)_!=NULL) ) {
//human 吃 v
v->VegetableFunction();
}
}
但是我们很容易就看出问题:
- 使用 if-else 结构,多了不容易处理
- 使用了动态类型识别和向下转型,违背了里氏替换原则,不易扩展
- 由于 Meat 和 Vegetable 会有不同的外部接口,难以在 Eat 中形成一致的行为
解决问题
聪明的 Human 很快就想到,他可以将 Eat 行为的具体实现,转移到 Food 及其子类中,并在子类中给出不同的实现:
再次分析
我们再仔细考虑下,问题真的全部解决了吗?
- 如果 Human 创造了子类 Male 类和 Female 类呢
- 如果 Human 系列增加一个 Cook(Food *) 操作呢
我们知道 Male 和 Female 吃 Food 方式是不同的。比如说 Male 对 Meat 的要求是大块的,对 Vegetable 的要求是多油的;而 Female 对 Meat 的要求是小块的,对 Vegetable 的要求则是清淡的。那么 Human 增加这两个子类后,Food 的方法实现如下:
void Meat::BeEaten(Human * human){
if ( (Female * female = dynamic_cast<Female * >(human))!= NULL ) {
// meat 被 female 吃
} else if ((Male * male = dynamic_cast<Male * >(human))!= NULL ) {