//
Purpose.?Composite, Builder, Iterator,
Memento, Visitor demo
//
// Discussion.?Composite is a fairly fundamental pattern - it uses, or is
//
used by, many other patterns.?Iterator
can be used to traverse a
// Composite [GOF, p173].?Visitor can be used to apply an operation
over
// an object structure defined by Composite [GOF, p344].?Builder often
// builds a Composite
[GOF, p106].?Iterator can use Memento
to capture
// the state of an iteration [GOF, p271].
//
// Input
(composit.dat):
//牋?a 1 2 b 6 d
13 14 15 d 7 8 b 3 4 5 c 9 10 11
//牋?
e 16 17 g 20 g 18 e 12 f 19 f c a
//
// In-memory
structures:
//牋?a:牋 1牋
2?^b牋 3牋 4牋 5?
^c
//牋?b:牋 6?
^d牋 7牋 8牋
//牋?c:牋
9?10?11?^e?12?
^f
//牋?d:?13?
14?15牋牋牋牋牋牋牋牋牋
//牋?
e:?16?17?^g?18
//牋?f:?19
//牋?g:?
20
//
// Output:
//牋?
1 2 6 13 14 15 7 8 3 4 5 9 10 11 16 17 20 18 12 19
//牋?a 1 2 b 6 d 13 14 15 7 8 3 4 5 c 9 10 11 e
16 17 g 20 18 12 f 19
//牋?
composites = 7.?primitives =
20.?total value = 210.?average value = 10
#include
<stdio.h>
#include <iostream.h>
#include
<fstream.h>
class Composite;
class Primitive;
class
Visitor {
public:
牋 virtual
void visit( Composite* ) = 0;
牋
virtual void visit( Primitive* ) = 0;
};
class
ListVisitor : public Visitor {
public:
牋 /* virtual */ void visit( Composite* );
牋 /* virtual */ void visit( Primitive*
);
};
class TotalVisitor : public Visitor {
public:
牋 TotalVisitor() { totalComposites =
totalPrimitives = totalValue = 0; }
牋
/* virtual */ void visit( Composite* c ) { totalComposites++; }
牋 /* virtual */ void visit( Primitive*
);
牋 void reportTotals()?{
牋牋?
cout << "composites = " << totalComposites
牋牋牋牋 << ".?primitives = " <<
totalPrimitives
牋牋牋牋 <<
".?total value = " <<
totalValue
牋牋牋牋 <<
".?average value = " <<
totalValue / totalPrimitives << endl; }
private:
牋 int?
totalComposites;
牋 int?totalPrimitives;
牋 int?
totalValue;
};
class Iterator;
class
Component {
public:
牋 enum
ComponentType { PrimitiveT, CompositeT };
牋 virtual void traverse()牋牋牋牋
= 0;
牋 virtual void add(
Component* )?{ }
牋 virtual ComponentType getType() = 0;
牋 virtual void accept( Visitor& ) =
0;
};
class Primitive : public Component {
public:
牋 Primitive( int _value )牋牋牋牋牋牋牋牋 { value_ = _value; }
牋 void traverse()牋牋牋牋牋牋牋牋牋牋牋牋 { cout << value_ << "
"; }
牋 ComponentType
getType()牋牋牋牋牋牋牋牋 { return
PrimitiveT; }
牋 int
getValue()牋牋牋牋牋牋牋牋牋牋牋牋?{
return value_; }
牋 /* virtual */
void accept( Visitor& v ) { v.visit( this ); }
private:
牋 int牋?
value_;
};
class Composite : public Component {
public:
牋 friend Iterator;
牋 Composite( char _name )牋牋牋牋牋牋牋牋 { name_ = _name;?index_ = 0; }
牋 void add( Component* ele )牋牋牋牋牋牋?{ children_[index_++] = ele;
}
牋 ComponentType getType()牋牋牋牋牋牋牋牋 { return CompositeT; }
牋 void printName()牋牋牋牋牋牋牋牋牋牋牋?{ cout << name_ << "
"; }
牋 /* virtual */ void
accept( Visitor& v ) { v.visit( this ); }
牋 void traverse();
牋
Iterator*?
createIterator();
private:
?
?/span>char牋牋牋?name_;
牋
int牋牋牋牋 index_;
牋 Component*?
children_[99];
};
void Composite::traverse() {
牋 for (int i=0; i < index_; i++)
牋牋?children_[i]->traverse(); }
/*
virtual */ void ListVisitor::visit( Composite* c ) { c->printName(); }
/*
virtual */ void ListVisitor::visit( Primitive* p ) { p->traverse(); }
/*
virtual */ void TotalVisitor::visit( Primitive* p ) {
牋 totalPrimitives++;
牋 totalValue += p->getValue(); }
class
Memento {
public:
牋 void
initialize( Composite* _root ) {
牋牋?
compArr_[0] = _root;
牋牋?
indxArr_[0] = -1;
牋牋?
index_ = 0; }
牋 void
pushCurrent( Composite* _composite, int _index ) {
牋牋?compArr_[index_+1] = _composite;
牋牋?indxArr_[++index_] = _index; }
牋 int popCurrent() {
牋牋?if (index_ == 0) return 1;
牋牋?index_--;
牋牋?return 0; }
牋 void getAndIncrement( Composite**
_composite, int* _index ) {
牋牋?
*_composite = compArr_[index_];
牋牋?*_index = indxArr_[index_];
牋牋?(*_index)++;
牋牋?
indxArr_[index_]++; }
private:
牋 Composite*?
compArr_[10];
牋 int牋牋牋牋 indxArr_[10];
牋 int牋牋牋牋
index_;
};
class Iterator {
public:
牋 Iterator( Composite* _root ) {
牋牋?root_ = _root;
牋牋?isDone_= 0; }
牋 Component* first() {
牋牋?isDone_= 0;
牋牋?memento_.initialize( root_ );
牋牋?return root_; }
牋 Component* next() {
牋牋?Composite* comp;
牋牋?int牋牋牋?indx;
牋牋?
memento_.getAndIncrement( &comp, &indx );
牋牋?// if (and while) you are at
end-of-composite, go back up
牋牋?
while (indx == comp->index_)
牋牋?{
牋牋牋牋 int
ret = memento_.popCurrent();
牋牋牋牋
if (ret) {
牋牋牋牋牋?
isDone_ = 1;
牋牋牋牋牋?
return 0; }
牋牋牋牋
memento_.getAndIncrement( &comp, &indx );
牋牋?}
牋牋?if (comp->children_[indx]->getType() ==
Component::CompositeT)
牋牋牋牋
memento_.pushCurrent( (Composite*) comp->children_[indx], -1 );
牋牋?return comp->children_[indx]; }
牋 int isDone() { return isDone_; }
private:
牋 Composite*?
root_;
牋 Memento牋牋 memento_;
牋 int牋牋牋牋
isDone_;
};
Iterator*?
Composite::createIterator() {
牋
return new Iterator( this ); }
class Builder;
class
Reader {
public:
牋 Reader(
Builder* _builder ) {
牋牋?
builder_ = _builder;
牋牋?
nextSlot_ = 0; }
牋 void
construct();
private:
牋
Builder*?builder_;
牋 char牋牋?
compNames_[20];
牋 int牋牋牋 nextSlot_;
牋 int isLower_( char ch ) {
牋牋?if ((ch >= 'a') && (ch <=
'z')) return 1;
牋牋?else return
0; }
牋 int findName_( char ch )
{
牋牋?for (int i=0; i <
nextSlot_; i++)
牋牋牋牋 if
(compNames_[i] == ch) return 1;
牋牋?
compNames_[nextSlot_++] = ch;
牋牋?
return 0; }
};
class Builder {
public:
牋 /**/ Builder()牋牋牋牋 { nextSlot_ = 0; }
牋
void buildComposite( char _name ) {
牋牋?// cout << _name << " at level "
<< nextSlot_ << endl;
牋牋?
stack_[nextSlot_] = new Composite( _name );
牋牋?if (nextSlot_)
牋牋牋牋 stack_[nextSlot_ - 1]->add(
stack_[nextSlot_] );
牋牋?
nextSlot_++; }
牋 void
buildPrimitive( int _value ) {
牋牋?
stack_[nextSlot_ - 1]->add( new Primitive( _value ) ); }
牋 void closeComposite()?{ nextSlot_--; }
牋 Composite* getResult() { return stack_[0];
}
private:
牋 Composite*
stack_[20];
牋 int牋牋牋?nextSlot_;
};
void
Reader::construct() {
牋 char牋牋?buf[20];
牋 int牋牋牋 value;
牋 ifstream?
inFile( "composit.dat", ios::in );
牋 while ( inFile >> buf )
牋 {
牋牋?if (isLower_( buf[0] ))
牋牋牋牋 if (findName_( buf[0] ))
牋牋牋牋牋?builder_->closeComposite();
牋牋牋牋 else
牋牋牋牋牋?builder_->buildComposite( buf[0] );
牋牋?else
牋牋?{
牋牋牋牋
sscanf( buf, "%d", &value );
牋牋牋牋 builder_->buildPrimitive( value
);
牋牋?}
牋 }
}
void main( void )
{
牋 Builder 牋牋牋builder;
牋 Reader牋牋牋?reader(
&builder );
牋 Composite*牋?root;
牋 Iterator*牋牋 it;
牋 ListVisitor牋 listV;
牋
TotalVisitor?totalV;
牋 reader.construct();
牋 root = builder.getResult();
牋 // Composite can traverse itself, but
Composite nodes get "lost"
牋
root->traverse();牋 cout
<< endl;
牋 // If you
don't want Composite nodes "lost", use an Iterator for
traversal
牋 it =
root->createIterator();
牋 for
(Component* c = it->first(); ! it->isDone(); c = it->next())
牋牋?c->accept( listV );
?/span>?cout
<< endl;
牋 // Visitors
can be designed to accumulate state over a Composite
牋 for (c = it->first(); ! it->isDone();
c = it->next())
牋牋?
c->accept( totalV );
牋
totalV.reportTotals();
}
// ListVisitor replaces the
following code:
// for (Component* c = it->first(); ! it->isDone();
c = it->next()) {
//牋?if
(c->getType() == Component::PrimitiveT)
//牋牋牋 ((Primitive*) c)->traverse();
//牋?else
//牋牋牋 ((Composite*) c)->printName(); }