Intent
Provide a way to access the elements of an aggregate object sequentially without
exposing its underlying representation.
// refactoringtopattern.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <vector>
#include <exception>
#define DEFAULT_LIST_CAPACITY 1024
template<class Item>
class Iterator {
public:
virtual void First() = 0;
virtual void Next() = 0;
virtual bool IsDone() const = 0;
virtual Item CurrentItem() const = 0;
protected:
Iterator() {
std::cout << __FUNCTION__ << std::endl;
}
};
template<class Item>
class IteratorPtr {
public:
IteratorPtr(Iterator<Item>* i) :i_(i) {}
~IteratorPtr() {
delete i_;
}
Iterator<Item>* operator->() {
return i_;
}
Iterator<Item>& operator*() {
return *i_;
}
private:
// multiple deletions of i_
IteratorPtr(const IteratorPtr&) {}
IteratorPtr& operator=(const IteratorPtr& a) {
return (*this);
}
private:
Iterator<Item>* i_;
};
// 抽象接口
template<class Item>
class AbstractList {
public:
AbstractList() {}
virtual Iterator<Item>* CreateIterator() const = 0;
};
template<typename Item>
class ListIterator;
// 实现接口
template<class Item>
class List : public AbstractList<Item>{
public:
List(long size = DEFAULT_LIST_CAPACITY) {
Item** new_item = new Item * [size];
for (int i = 0; i < size; i++)
{
new_item[i] = new Item();
}
item_ = new_item;
item_count_ = size;
}
long Count() const {
return item_count_;
}
Item& Get(long index) const {
return *(*(item_ + index));
}
virtual Iterator<Item>* CreateIterator() const {
return new ListIterator<Item>(this);
}
private:
Item** item_;
long item_count_;
};
class IteratorOutOfBounds : public std::exception {
public:
const char* what() const throw() {
return "son of bitch!";
}
};
template<class Item>
class ListIterator : public Iterator<Item> {
public:
ListIterator(const List<Item>* aList) :Iterator<Item>(),list_(aList), current_(static_cast<long>(0)) {
}
virtual void First() {
current_ = 0;
}
virtual void Next() {
current_++;
}
virtual bool IsDone() const {
return current_ >= list_->Count();
}
virtual Item CurrentItem() const {
// c++ primer : exception
if (IsDone()) {
throw IteratorOutOfBounds();
}
return list_->Get(current_);
}
private:
const List<Item>* list_;
long current_;
};
template<class Item>
class ListTraverser {
public:
ListTraverser(List<Item>* aList) :iterator_(aList) {}
bool Traverse() {
bool result = false;
for (iterator_.First(); !iterator_.IsDone(); iterator_.Next()) {
result = ProcessItem(iterator_.CurrentItem());
if (result == false)
break;
}
return result;
}
protected:
virtual bool ProcessItem(const Item&) = 0;
private:
ListIterator<Item> iterator_;
};
class Employee {
public:
Employee() {}
~Employee() {}
void Print() {
std::cout << __FUNCTION__ << std::endl;
}
};
class PrintNEmployees : public ListTraverser<Employee*> {
public:
PrintNEmployees(List<Employee*>* aList, int n) :
ListTraverser<Employee*>(aList),
total_(n), count_(0) {}
protected:
bool ProcessItem(Employee* const& e) {
count_++;
e->Print();
return count_ < total_;
}
private:
int total_;
int count_;
};
template<class Item>
class FilteringListTraverser {
public:
FilteringListTraverser(List<Item>* aList) :iterator_(aList){}
bool Traverse() {
bool result = false;
for (iterator_.First(); !iterator_.IsDone(); iterator_.Next()) {
if (TestItem(iterator_.CurrentItem()))
{
result = ProcessItem(iterator_.CurrentItem());
if (result == false)
break;
}
}
return result;
}
protected:
virtual bool ProcessItem(const Item&) = 0;
virtual bool TestItem(const Item&) = 0;
private:
ListIterator<Item> iterator_;
};
void PrintEmployees(Iterator<Employee*>& i) {
for (i.First(); !i.IsDone(); i.Next()) {
i.CurrentItem()->Print();
}
}
int main()
{
{
AbstractList<Employee*>* employees = new List<Employee*>(9);
IteratorPtr<Employee*> iterator(employees->CreateIterator());
PrintEmployees(*iterator);
}
{
List<Employee*>* employees = new List<Employee*>(10);
PrintNEmployees pa(employees, 10);
pa.Traverse();
}
{ // prints the first 10 employees
List<Employee*>* employees = new List<Employee*>(5);
ListIterator<Employee*> i(employees);
int count = 0;
for (i.First(); !i.IsDone(); i.Next()) {
count++;
i.CurrentItem()->Print();
if (count >= 3)
break;
}
}
}