Iterator

use strict;
use warnings;

{
    package Aggregate;
    use strict;
    use warnings;
    sub iterator { die "use OverRide"; }
}

{
    package Iterator;
    use strict;
    use warnings;
    sub hasNext { die "use OrverRide"; }
    sub next { die "use OverRide"; }
}

{
    package Book;
    use strict;
    use warnings;
    sub new {
        my ($class, $book) = @_;
        my $self = {
            name => $book
        };
        return bless $self, $class;
    }
    sub getName {
        $_[0]->{name};
    }
}

{
    package BookShelf;
    use strict;
    use warnings;
    our @ISA = qw/Aggregate/;
    sub new {
        my ($class, ) = @_;
        my $self = {
            books => [],
            last  => 0,
        };
        return bless $self, $class;
    }
    sub getBookAt {
        my ($self, $index) = @_;
        return $self->{books}[$index];
    }
    sub appendBook {
        my ($self, $book) = @_;
        $self->{books}[$self->{last}] = $book;
        $self->{last}++;
    }
    sub getLength {
        $_[0]->{last};
    }
    sub iterator {
        my $self = shift;
        return BookShelfIterator->new($self);
    }
}

{
    package BookShelfIterator;
    use strict;
    use warnings;
    our @ISA = qw/Iterator/;
    sub new {
        my ($class, $bookShelf) = @_;
        my $self = {
            bookShelf => $bookShelf,
            index     => 0,
        };
        return bless $self, $class;
    }
    sub hasNext {
        my $self = shift;
        if($self->{index} < $self->{bookShelf}->getLength()){
            return 1;
        } else {
            return 0;
        }
    }
    sub next {
        my $self = shift;
        my $book = $self->{bookShelf}->getBookAt($self->{index});
        $self->{index}++;
        return $book;
    }
}


use Data::Dumper;

my $bookShelf = BookShelf->new();
$bookShelf->appendBook(Book->new('PROGRAMMING1'));
$bookShelf->appendBook(Book->new('PROGRAMMING2'));
$bookShelf->appendBook(Book->new('PROGRAMMING3'));

my $iterator = $bookShelf->iterator();
while($iterator->hasNext()){
    my $book = $iterator->next();
    print $book->getName(),"\n";
}