Qua các series tự học về Design Pattern, Hôm nay cafedevn chia sẻ cho ace ví dụ và code cụ thể về cách sử dụng Iterator design pattern với ngôn ngữ lập trình PHP. Nhằm giúp ace hiểu rõ cách sử Pattern này với PHP một cách nhanh nhất và áp dụng nó vào thực tế.

Mô tả code

Trong ví dụ này, lớp BookList sẽ được lưu trữ từ 0 đến nhiều phần tử của lớp Book. BookListIterator có thể trả lại lần lượt tất cả các Book trong BookList và theo thứ tự tuần tự mà các phần tử Book đã được thêm vào BookList.

Tôi cũng hiển thị một BookListReverseIterator. BookListReverseIterator có thể trả lại lần lượt tất cả các Sách trong BookList và theo thứ tự tuần tự ngược lại mà các phần tử Sách đã được thêm vào BookList. Điều này được thêm vào để cho thấy rằng các trình vòng lặp tùy chỉnh có thể khá hữu ích khi bạn cần xử lý một danh sách theo một trình tự khác với tuần tự từ đầu đến cuối. Trong khi iterators này ngược lại, tôi cũng có thể hiển thị một trình lặp trả về, ví dụ, chỉ các phần tử được đánh số lẻ.

Lưu ý rằng các iterators được hiển thị không “mạnh” và sẽ mang lại kết quả không thể đoán trước được nếu List mà iterators đang xử lý có các phần tử bị loại bỏ trong khi iterators đang duyệt qua List . 

Phần code

<?php

class Book {
    private $author;
    private $title;
    function __construct($title_in, $author_in) {
      $this->author = $author_in;
      $this->title  = $title_in;
    }
    function getAuthor() {return $this->author;}
    function getTitle() {return $this->title;}
    function getAuthorAndTitle() {
      return $this->getTitle() . ' by ' . $this->getAuthor();
    }
}

class BookList {
    private $books = array();
    private $bookCount = 0;
    public function __construct() {
    }
    public function getBookCount() {
      return $this->bookCount;
    }
    private function setBookCount($newCount) {
      $this->bookCount = $newCount;
    }
    public function getBook($bookNumberToGet) {
      if ( (is_numeric($bookNumberToGet)) && 
           ($bookNumberToGet <= $this->getBookCount())) {
           return $this->books[$bookNumberToGet];
         } else {
           return NULL;
         }
    }
    public function addBook(Book $book_in) {
      $this->setBookCount($this->getBookCount() + 1);
      $this->books[$this->getBookCount()] = $book_in;
      return $this->getBookCount();
    }
    public function removeBook(Book $book_in) {
      $counter = 0;
      while (++$counter <= $this->getBookCount()) {
        if ($book_in->getAuthorAndTitle() == 
          $this->books[$counter]->getAuthorAndTitle())
          {
            for ($x = $counter; $x < $this->getBookCount(); $x++) {
              $this->books[$x] = $this->books[$x + 1];
          }
          $this->setBookCount($this->getBookCount() - 1);
        }
      }
      return $this->getBookCount();
    }
}

class BookListIterator {
    protected $bookList;
    protected $currentBook = 0;

    public function __construct(BookList $bookList_in) {
      $this->bookList = $bookList_in;
    }
    public function getCurrentBook() {
      if (($this->currentBook > 0) && 
          ($this->bookList->getBookCount() >= $this->currentBook)) {
        return $this->bookList->getBook($this->currentBook);
      }
    }
    public function getNextBook() {
      if ($this->hasNextBook()) {
        return $this->bookList->getBook(++$this->currentBook);
      } else {
        return NULL;
      }
    }
    public function hasNextBook() {
      if ($this->bookList->getBookCount() > $this->currentBook) {
        return TRUE;
      } else {
        return FALSE;
      }
    }
}

class BookListReverseIterator extends BookListIterator {
    public function __construct(BookList $bookList_in) {
      $this->bookList = $bookList_in;
      $this->currentBook = $this->bookList->getBookCount() + 1;
    }
    public function getNextBook() {
      if ($this->hasNextBook()) {
        return $this->bookList->getBook(--$this->currentBook);
      } else {
        return NULL;
      }
    }
    public function hasNextBook() {
      if (1 < $this->currentBook) {
        return TRUE;
      } else {
        return FALSE;
      }
    }
}


  writeln('BEGIN TESTING ITERATOR PATTERN');
  writeln('');
 
  $firstBook = new Book('Core PHP Programming, Third Edition', 'Atkinson and Suraski');
  $secondBook = new Book('PHP Bible', 'Converse and Park');
  $thirdBook = new Book('Design Patterns', 'Gamma, Helm, Johnson, and Vlissides');

  $books = new BookList();
  $books->addBook($firstBook);
  $books->addBook($secondBook);
  $books->addBook($thirdBook);
 
  writeln('Testing the Iterator');
 
  $booksIterator = new BookListIterator($books);

  while ($booksIterator->hasNextBook()) {
    $book = $booksIterator->getNextBook();
    writeln('getting next book with iterator :');
    writeln($book->getAuthorAndTitle());
    writeln('');
  }
 
  $book = $booksIterator->getCurrentBook();
  writeln('getting current book with iterator :');
  writeln($book->getAuthorAndTitle());
  writeln('');  

  writeln('Testing the Reverse Iterator');

  $booksReverseIterator = new BookListReverseIterator($books);

  while ($booksReverseIterator->hasNextBook()) {
    $book = $booksReverseIterator->getNextBook();
    writeln('getting next book with reverse iterator :');
    writeln($book->getAuthorAndTitle());
    writeln('');
  }
 
  $book = $booksReverseIterator->getCurrentBook();
  writeln('getting current book with reverse iterator :');
  writeln($book->getAuthorAndTitle());
  writeln('');

  writeln('END TESTING ITERATOR PATTERN');
 
  function writeln($line_in) {
    echo $line_in."<br/>";
  }

?>

Kết quả:

BEGIN TESTING ITERATOR PATTERN

Testing the Iterator
getting next book with iterator : 
Core PHP Programming, Third Edition by Atkinson and Suraski

getting next book with iterator : 
PHP Bible by Converse and Park

getting next book with iterator : 
Design Patterns by Gamma, Helm, Johnson, and Vlissides

getting current book with iterator : 
Design Patterns by Gamma, Helm, Johnson, and Vlissides

Testing the Reverse Iterator
getting next book with reverse iterator : 
Design Patterns by Gamma, Helm, Johnson, and Vlissides

getting next book with reverse iterator : 
PHP Bible by Converse and Park

getting next book with reverse iterator : 
Core PHP Programming, Third Edition by Atkinson and Suraski

getting current book with reverse iterator : 
Core PHP Programming, Third Edition by Atkinson and Suraski

END TESTING ITERATOR PATTERN

Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.

Tài liệu từ cafedev:

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!