Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Thinking In C++, 2nd Edition, Volume 2 Standard Libraries& Advanced Topics - Eckel B..pdf
Скачиваний:
313
Добавлен:
24.05.2014
Размер:
2.09 Mб
Скачать

cout << a << "\t" << b << "\t"; return a->compete(b);

}

};

int main() {

const int sz = 20; vector<Item*> v(sz*2);

generate(v.begin(), v.end(), ItemGen()); transform(v.begin(), v.begin() + sz,

v.begin() + sz, ostream_iterator<Outcome>(cout, "\n"), Compete());

purge(v); } ///:~

Visitor, a type of multiple dispatching

The assumption is that you have a primary class hierarchy that is fixed; perhaps it’s from another vendor and you can’t make changes to that hierarchy. However, you’d like to add new polymorphic methods to that hierarchy, which means that normally you’d have to add something to the base class interface. So the dilemma is that you need to add methods to the base class, but you can’t touch the base class. How do you get around this?

The design pattern that solves this kind of problem is called a “visitor” (the final one in the Design Patterns book), and it builds on the double dispatching scheme shown in the last section.

The visitor pattern allows you to extend the interface of the primary type by creating a separate class hierarchy of type Visitor to virtualize the operations performed upon the primary type. The objects of the primary type simply “accept” the visitor, then call the visitor’s dynamically-bound member function.

//: C09:BeeAndFlowers.cpp

// Demonstration of "visitor" pattern #include "../purge.h"

#include <iostream> #include <string> #include <vector> #include <algorithm> #include <cstdlib> #include <ctime> using namespace std;

class Gladiolus;

Chapter 16: Design Patterns

463

class Renuculus; class Chrysanthemum;

class Visitor { public:

virtual void visit(Gladiolus* f) = 0; virtual void visit(Renuculus* f) = 0; virtual void visit(Chrysanthemum* f) = 0; virtual ~Visitor() {}

};

class Flower { public:

virtual void accept(Visitor&) = 0; virtual ~Flower() {}

};

class Gladiolus : public Flower { public:

virtual void accept(Visitor& v) { v.visit(this);

}

};

class Renuculus : public Flower { public:

virtual void accept(Visitor& v) { v.visit(this);

}

};

class Chrysanthemum : public Flower { public:

virtual void accept(Visitor& v) { v.visit(this);

}

};

// Add the ability to produce a string: class StringVal : public Visitor {

string s; public:

operator const string&() { return s; } virtual void visit(Gladiolus*) {

Chapter 16: Design Patterns

464

s = "Gladiolus";

}

virtual void visit(Renuculus*) { s = "Renuculus";

}

virtual void visit(Chrysanthemum*) { s = "Chrysanthemum";

}

};

// Add the ability to do "Bee" activities: class Bee : public Visitor {

public:

virtual void visit(Gladiolus*) { cout << "Bee and Gladiolus\n";

}

virtual void visit(Renuculus*) { cout << "Bee and Renuculus\n";

}

virtual void visit(Chrysanthemum*) { cout << "Bee and Chrysanthemum\n";

}

};

struct FlowerGen {

FlowerGen() { srand(time(0)); } Flower* operator()() {

switch(rand() % 3) { default:

case 0: return new Gladiolus; case 1: return new Renuculus; case 2: return new Chrysanthemum;

}

}

};

int main() { vector<Flower*> v(10);

generate(v.begin(), v.end(), FlowerGen()); vector<Flower*>::iterator it;

//It's almost as if I added a virtual function

//to produce a Flower string representation: StringVal sval;

for(it = v.begin(); it != v.end(); it++) {

Chapter 16: Design Patterns

465

Соседние файлы в предмете Программирование