DesignPatterns_Iterator

/
// Iterator
// - Provide a way to access the elements of an aggregate object sequentially without
//   exposing its underlying representation.
//
// Author     : ZAsia
// Date       : 15/05/14
// Warning    : In practice, declaration and implementation should
//              be separated(.h and .cpp).
/
#include 
  
  
   
   
using namespace std;

#define DEFAULT_CAPACITY 128

// Iterator
// - defines an interface for accessing and traversing elements.
template 
   
   
    
    
class Iterator
{
public:
	virtual void First() = 0;
	virtual void Next() = 0;
	virtual bool IsDone() const = 0;
	virtual Item CurrentItem() const = 0;
};

// forward declaration
template 
    
    
     
     
class ConcreteAggregate;

// ConcreteIterator
// - implements the Iterator interface.
// - keep the track of the current position in the traversal of the aggregate.
//
// - the implementation of ReverseIterator is identical, except its First operation
//   positions _current to the end of the ConcreteAggregate, and Next decrements 
//   _current toward the first item.
template 
     
     
      
      
class ConcreteIterator : public Iterator
      
      
        { public: ConcreteIterator(const ConcreteAggregate 
       
         *aggr) : _aggr(aggr), _current(0) { } // First positions the iterator to the first element. virtual void First() { _current = 0; } // Next advances the current element. virtual void Next() { if (_current < _aggr->Count()) { ++_current; } } // IsDone checks whether the index refers to an element within the List. virtual bool IsDone() const { return _current >= _aggr->Count(); } // CurrentItem returns the item at the current index. // If the iteration has already terminated, then throw an exception. virtual Item CurrentItem() const { if (IsDone()) { cout << "Iterator out of bounds." << endl; return 0; } return _aggr->Get(_current); } private: const ConcreteAggregate 
        
          *_aggr; long _current; }; // Aggregate // - defines an interface for creating an Iterator object. template 
         
           class Aggregate { public: Aggregate( ) { } virtual ~Aggregate() { } virtual ConcreteIterator 
          
            *CreateIterator() = 0; virtual void Append(Item item) = 0; virtual void Remove(Item item) = 0; virtual long Count() const = 0; virtual Item Get(long index) const = 0; }; // ConcreteAggregate // - implements the Iterator creation interface to return an instance of the // proper ConcreteIterator. template 
           
             class ConcreteAggregate : public Aggregate 
            
              { public: ConcreteAggregate() : _size(0), _iter(nullptr) { } virtual ConcreteIterator 
             
               *CreateIterator() { if (_iter) { return _iter; } return new ConcreteIterator 
              
                (this); } virtual void Append(Item item) { if (_size > DEFAULT_CAPACITY) { cout << "Aggregate out of capacity." << endl; return; } _arr[_size++] = item; } virtual void Remove(Item item) { if (_size == 0) { return; } for (int i = 0; i < _size; ++i) { if (_arr[i] == item) { for (int j = i; j < _size - 1; ++j) { _arr[j] = _arr[j + 1]; } --_size; } } } virtual long Count() const { return _size; } virtual Item Get(long index) const { return _arr[index]; } private: ConcreteIterator 
               
                 *_iter; long _size; Item _arr[DEFAULT_CAPACITY]; }; // Collaborations // - A ConcreteIterator keeps track of the current object in the aggregate and // can compute the succeeding object in the traversal. int main() { ConcreteAggregate 
                
                  aggregate; for (long item = 0; item < 21; ++item) { aggregate.Append(item); } aggregate.Remove(15); ConcreteIterator 
                 
                   *pIterator = aggregate.CreateIterator(); for (pIterator->First(); !pIterator->IsDone(); pIterator->Next()) { cout << pIterator->CurrentItem() << endl; } if (pIterator) { delete pIterator; pIterator = nullptr; } return 0; } /// // 1. How robust is the iterator? It can be dangerous to modify an aggregate while // you'r traversing it. A robust iterator most rely on registering the iterator // with the aggregate. On insertion or removal, the aggregate either adjusts the // internal state of iterators it has produced, or it maintains information // internally to ensure proper traversal. // 2. Polymorphic iterators have another drawback: the client is responsible for // deleting them. This is error-prone, because it's easy to forget to free a // heap-allocated when you're finished with it. And if an exception is triggered, // the iterator object will never be freed. 
                  
                 
                
               
              
             
            
           
          
         
        
      
     
     
    
    
   
   
  
  


// 1. Making sure iterators get deleted. Notice that CreateIterator returns a 
// newly allocated iterator object. We're responsible for deleting it. If
// we forget, then we've created storage leak. To make life easier for client,
// we'll provide an IteratorPtr that acts as a proxy for an iterator. It takes
// care of cleaning up the Iterator object when it goes out of scope.
// 2. IteratorPtr is always allocated on the stack. C++ automatically takes care
// of calling its destructor, which deletes the real iterator. 

/
// Iterator
// - Provide a way to access the elements of an aggregate object sequentially without
//   exposing its underlying representation.
//
// Author     : ZAsia
// Date       : 15/05/14
// Warning    : In practice, declaration and implementation should
//              be separated(.h and .cpp).
/
#include 
   
   
    
    
using namespace std;

#define DEFAULT_CAPACITY 128

// Iterator
// - defines an interface for accessing and traversing elements.
template 
    
    
     
     
class Iterator
{
public:
	virtual void First() = 0;
	virtual void Next() = 0;
	virtual bool IsDone() const = 0;
	virtual Item CurrentItem() const = 0;
};

// forward declaration
template 
     
     
      
      
class ConcreteAggregate;

// ConcreteIterator
// - implements the Iterator interface.
// - keep the track of the current position in the traversal of the aggregate.
//
// - the implementation of ReverseIterator is identical, except its First operation
//   positions _current to the end of the ConcreteAggregate, and Next decrements 
//   _current toward the first item.
template 
      
      
       
       
class ConcreteIterator : public Iterator
       
       
         { public: ConcreteIterator(const ConcreteAggregate 
        
          *aggr) : _aggr(aggr), _current(0) { } // First positions the iterator to the first element. virtual void First() { _current = 0; } // Next advances the current element. virtual void Next() { if (_current < _aggr->Count()) { ++_current; } } // IsDone checks whether the index refers to an element within the List. virtual bool IsDone() const { return _current >= _aggr->Count(); } // CurrentItem returns the item at the current index. // If the iteration has already terminated, then throw an exception. virtual Item CurrentItem() const { if (IsDone()) { cout << "Iterator out of bounds." << endl; return 0; } return _aggr->Get(_current); } private: const ConcreteAggregate 
         
           *_aggr; long _current; }; // Aggregate // - defines an interface for creating an Iterator object. template 
          
            class Aggregate { public: Aggregate( ) { } virtual ~Aggregate() { } virtual ConcreteIterator 
           
             *CreateIterator() = 0; virtual void Append(Item item) = 0; virtual void Remove(Item item) = 0; virtual long Count() const = 0; virtual Item Get(long index) const = 0; }; // ConcreteAggregate // - implements the Iterator creation interface to return an instance of the // proper ConcreteIterator. template 
            
              class ConcreteAggregate : public Aggregate 
             
               { public: ConcreteAggregate() : _size(0), _iter(nullptr) { } virtual ConcreteIterator 
              
                *CreateIterator() { if (_iter) { return _iter; } return new ConcreteIterator 
               
                 (this); } virtual void Append(Item item) { if (_size > DEFAULT_CAPACITY) { cout << "Aggregate out of capacity." << endl; return; } _arr[_size++] = item; } virtual void Remove(Item item) { if (_size == 0) { return; } for (int i = 0; i < _size; ++i) { if (_arr[i] == item) { for (int j = i; j < _size - 1; ++j) { _arr[j] = _arr[j + 1]; } --_size; } } } virtual long Count() const { return _size; } virtual Item Get(long index) const { return _arr[index]; } private: ConcreteIterator 
                
                  *_iter; long _size; Item _arr[DEFAULT_CAPACITY]; }; // IteratorPtr // 1. Making sure iterators get deleted. Notice that CreateIterator returns a // newly allocated iterator object. We're responsible for deleting it. If // we forget, then we've created storage leak. To make life easier for client, // we'll provide an IteratorPtr that acts as a proxy for an iterator. It takes // care of cleaning up the Iterator object when it goes out of scope. // 2. IteratorPtr is always allocated on the stack. C++ automatically takes care // of calling its destructor, which deletes the real iterator. template 
                 
                   class IteratorPtr { public: IteratorPtr(Iterator 
                  
                    *i) : _i(i) { } ~IteratorPtr() { delete _i; } Iterator 
                   
                     *operator->() { return _i; } Iterator 
                    
                      &operator*() { return *_i; } private: // disallow copy and assignment to avoid multiple deletions of _i IteratorPtr(const IteratorPtr &ip) { } IteratorPtr &operator=(const IteratorPtr &rs) { } private: Iterator 
                     
                       *_i; }; // Collaborations // - A ConcreteIterator keeps track of the current object in the aggregate and // can compute the succeeding object in the traversal. int main() { ConcreteAggregate 
                      
                        aggregate; for (long item = 0; item < 21; ++item) { aggregate.Append(item); } aggregate.Remove(15); // ConcreteIterator 
                       
                         *pIterator = aggregate.CreateIterator(); IteratorPtr 
                        
                          iterator(aggregate.CreateIterator()); for (iterator->First(); !iterator->IsDone(); iterator->Next()) { cout << iterator->CurrentItem() << endl; } // if (pIterator) // { /// delete pIterator; // pIterator = nullptr; // } return 0; } /// // 1. How robust is the iterator? It can be dangerous to modify an aggregate while // you'r traversing it. A robust iterator most rely on registering the iterator // with the aggregate. On insertion or removal, the aggregate either adjusts the // internal state of iterators it has produced, or it maintains information // internally to ensure proper traversal. // 2. Polymorphic iterators have another drawback: the client is responsible for // deleting them. This is error-prone, because it's easy to forget to free a // heap-allocated when you're finished with it. And if an exception is triggered, // the iterator object will never be freed. 
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值