Trước tiên, chúng ta hãy cùng cafedev giới thiệu mọi thứ về Iterator Pattern và phần code ví dụ chi tiết nhằm giúp ace dễ hiểu khi áp dụng trên các ngôn ngữ khác nhau. Ace có thể tham khảo thêm các bài khác tại series Design Pattern tại đây.
Iterator Pattern là một design pattern tương đối đơn giản và được sử dụng thường xuyên. Có rất nhiều cấu trúc / bộ sưu tập dữ liệu có sẵn trong mọi ngôn ngữ. Mỗi bộ sưu tập phải cung cấp một trình lặp(Iterator) cho phép nó lặp qua các đối tượng của nó. Tuy nhiên, trong khi làm như vậy, nó phải đảm bảo rằng nó không để lộ việc triển khai.
Giả sử chúng ta đang xây dựng một ứng dụng yêu cầu chúng ta duy trì một danh sách các thông báo. Cuối cùng, một số phần code của bạn sẽ yêu cầu lặp lại tất cả các thông báo. Nếu chúng ta triển khai bộ sưu tập thông báo của bạn dưới dạng mảng, bạn sẽ lặp lại chúng dưới dạng:
// If a simple array is used to store notifications
for (int i = 0; i < notificationList.length; i++)
Notification notification = notificationList[i]);
// If ArrayList is Java is used, then we would iterate
// over them as:
for (int i = 0; i < notificationList.size(); i++)
Notification notification = (Notification)notificationList.get(i);
Và nếu đó là một số bộ sưu tập khác như set, tree, v.v. thì cách lặp sẽ thay đổi một chút. Bây giờ, điều gì sẽ xảy ra nếu chúng ta xây dựng một trình lặp(Iterator) cung cấp một cách chung để lặp qua một tập hợp độc lập với kiểu của nó.
// Create an iterator
Iterator iterator = notificationList.createIterator();
// It wouldn’t matter if list is Array or ArrayList or
// anything else.
while (iterator.hasNext())
{
Notification notification = iterator.next());
}
Iterator pattern cho phép chúng ta làm điều đó. Về mặt hình thức, nó được định nghĩa như sau:
Iterator pattern cung cấp một cách để truy cập các phần tử của một đối tượng tập hợp mà không làm lộ ra biểu hiện cơ bản của nó.
Sơ đồ lớp:
Ở đây chúng ta có một giao diện(interface) chung Aggregate cho client vì nó tách nó ra khỏi việc triển khai tập hợp các đối tượng của bạn. ConcreteAggregate triển khai createIterator() trả về trình lặp(Iterator) cho bộ sưu tập của nó. Trách nhiệm của mỗi ConcreteAggregate là khởi tạo một ConcreteIterator có thể lặp qua tập hợp các đối tượng của nó. Interface trình vòng lặp(iterator) cung cấp một tập hợp các phương thức để duyệt hoặc sửa đổi tập hợp, ngoài next () / hasNext (), nó cũng có thể cung cấp các chức năng để tìm kiếm, xóa, v.v.
Hãy hiểu điều này thông qua một ví dụ. Giả sử chúng ta đang tạo một thanh thông báo trong ứng dụng của mình để hiển thị tất cả các thông báo được giữ trong một bộ sưu tập thông báo. NotificationCollection cung cấp một trình lặp(iterator) để lặp qua các phần tử của nó mà không tiết lộ cách nó đã triển khai bộ sưu tập (mảng trong trường hợp này) cho Client(NotificationBar).
Sơ đồ lớp sẽ là:
Dưới đây là cách triển khai trong Java code:
// A Java program to demonstrate implementation
// of iterator pattern with the example of
// notifications
// A simple Notification class
class Notification
{
// To store notification message
String notification;
public Notification(String notification)
{
this.notification = notification;
}
public String getNotification()
{
return notification;
}
}
// Collection interface
interface Collection
{
public Iterator createIterator();
}
// Collection of notifications
class NotificationCollection implements Collection
{
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
Notification[] notificationList;
public NotificationCollection()
{
notificationList = new Notification[MAX_ITEMS];
// Let us add some dummy notifications
addItem("Notification 1");
addItem("Notification 2");
addItem("Notification 3");
}
public void addItem(String str)
{
Notification notification = new Notification(str);
if (numberOfItems >= MAX_ITEMS)
System.err.println("Full");
else
{
notificationList[numberOfItems] = notification;
numberOfItems = numberOfItems + 1;
}
}
public Iterator createIterator()
{
return new NotificationIterator(notificationList);
}
}
// We could also use Java.Util.Iterator
interface Iterator
{
// indicates whether there are more elements to
// iterate over
boolean hasNext();
// returns the next element
Object next();
}
// Notification iterator
class NotificationIterator implements Iterator
{
Notification[] notificationList;
// maintains curr pos of iterator over the array
int pos = 0;
// Constructor takes the array of notifiactionList are
// going to iterate over.
public NotificationIterator (Notification[] notificationList)
{
this.notificationList = notificationList;
}
public Object next()
{
// return next element in the array and increment pos
Notification notification = notificationList[pos];
pos += 1;
return notification;
}
public boolean hasNext()
{
if (pos >= notificationList.length ||
notificationList[pos] == null)
return false;
else
return true;
}
}
// Contains collection of notifications as an object of
// NotificationCollection
class NotificationBar
{
NotificationCollection notifications;
public NotificationBar(NotificationCollection notifications)
{
this.notifications = notifications;
}
public void printNotifications()
{
Iterator iterator = notifications.createIterator();
System.out.println("-------NOTIFICATION BAR------------");
while (iterator.hasNext())
{
Notification n = (Notification)iterator.next();
System.out.println(n.getNotification());
}
}
}
// Driver class
class Main
{
public static void main(String args[])
{
NotificationCollection nc = new NotificationCollection();
NotificationBar nb = new NotificationBar(nc);
nb.printNotifications();
}
}
Đầu ra:
-------NOTIFICATION BAR------------
Notification 1
Notification 2
Notification 3
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:
- Full series tự học Design Pattern từ cơ bản tới nâng cao tại đây nha.
- Các nguồn kiến thức MIỄN PHÍ VÔ GIÁ từ cafedev tại đây
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!