Mục đích
Iterator Pattern là một mẫu thiết kế hành vi, cho phép bạn duyệt qua tất cả các phần tử trong một tập hợp mà không cần tiết lộ cấu trúc dữ liệu nền của tập hợp (như danh sách, ngăn xếp và cây).
Điều kiện áp dụng
- Khi cấu trúc dữ liệu phía sau tập hợp là phức tạp và bạn muốn ẩn đi sự phức tạp đó khỏi khách hàng (vì sự tiện lợi hoặc vấn đề bảo mật), bạn có thể sử dụng Iterator Pattern.
- Sử dụng mẫu này có thể giảm số lượng mã lặp lại trong chương trình.
- Nếu bạn muốn mã của bạn có thể duyệt qua các cấu trúc dữ liệu khác nhau, thậm chí là các cấu trúc dữ liệu không thể dự đoán trước, bạn có thể sử dụng Iterator Pattern.
Cấu trúc
Giải thích cấu trúc
- Iterator (Iterator) là một giao diện khai báo các hoạt động cần thiết để duyệt qua tập hợp: lấy phần tử tiếp theo, lấy vị trí hiện tại và bắt đầu lại việc duyệt.
- ConcreteIterator (Concrete Iterators) triển khai một thuật toán cụ thể để duyệt qua tập hợp. Đối tượng Iterator phải theo dõi tiến trình duyệt của nó. Điều này cho phép nhiều Iterator có thể duyệt qua cùng một tập hợp mà không ảnh hưởng lẫn nhau.
- Collection (Collection) là một giao diện khai báo một hoặc nhiều phương thức để lấy Iterator tương thích với tập hợp. Lưu ý rằng kiểu trả về của phương thức phải được khai báo là giao diện Iterator, do đó Collection cụ thể có thể trả về nhiều loại Iterator khác nhau.
- ConcreteCollection (Concrete Collections) trả về một phiên bản cụ thể của ConcreteIterator khi được yêu cầu bởi khách hàng. Bạn có thể tự hỏi, phần còn lại của mã của Collection ở đâu? Đừng lo lắng, nó cũng nằm trong cùng một lớp. Chỉ là các chi tiết này không quan trọng đối với mẫu thực tế, vì vậy chúng tôi đã bỏ qua nó.
- Client (Client) tương tác với Collection và Iterator thông qua giao diện của chúng. Điều này cho phép khách hàng không cần phụ thuộc vào các lớp cụ thể, cho phép cùng mã khách hàng có thể sử dụng nhiều loại Collection và Iterator khác nhau.
- Thông thường, khách hàng không tự tạo Iterator mà lấy nó từ Collection. Tuy nhiên, trong một số trường hợp cụ thể, khách hàng có thể tạo một Iterator trực tiếp (ví dụ: khi khách hàng cần tạo một Iterator đặc biệt).
Mã mẫu cấu trúc
Iterator: Định nghĩa giao diện truy cập các phần tử.
ConcreteIterator: Triển khai giao diện Iterator. Ghi nhớ vị trí hiện tại của phần tử trong tập hợp.
Aggregate: Định nghĩa giao diện để tạo đối tượng Iterator.
ConcreteAggregate: Triển khai giao diện Iterator, trả về một phiên bản cụ thể của ConcreteIterator.
Khách hàng
Kết quả
Người đầu tiên là: AA
Danh sách tất cả mọi người:
AA
BB
CC
DD
Pseudo code
Trong ví dụ này, mẫu Iterator được sử dụng để lặp qua một tập hợp đặc biệt chứa chức năng truy cập vào quan hệ bạn bè trên WeChat. Tập hợp này cung cấp nhiều Iterator khác nhau để lặp qua thông tin hồ sơ.
Iterator “friends” được sử dụng để lặp qua danh sách bạn bè của một hồ sơ cụ thể. Iterator “colleagues” cũng cung cấp chức năng tương tự, nhưng chỉ bao gồm những người bạn làm việc cùng trong cùng một công ty với người dùng mục tiêu. Cả hai Iterator này đều triển khai cùng một giao diện chung, cho phép khách hàng truy cập vào hồ sơ mà không cần biết chi tiết về xác thực và gửi yêu cầu REST.
Khách hàng chỉ tương tác với tập hợp và Iterator thông qua giao diện, do đó không có sự ràng buộc với các lớp cụ thể. Nếu bạn quyết định kết nối ứng dụng với mạng xã hội hoàn toàn mới, bạn chỉ cần cung cấp các lớp tập hợp và Iterator mới mà không cần sửa đổi mã hiện có.
Ví dụ
Sử dụng ví dụ: Mẫu này rất phổ biến trong mã Java. Nhiều framework và thư viện sử dụng nó để cung cấp cách tiêu chuẩn để lặp qua các tập hợp của chúng.
Dưới đây là một số ví dụ trong thư viện Java cốt lõi:
- Tất cả các triển khai của
java.util.Iterator
(cũng nhưjava.util.Scanner
). - Tất cả các triển khai của
java.util.Enumeration
.
Cách nhận biết: Iterator có thể dễ dàng nhận biết thông qua các phương thức điều hướng như next
và previous
. Mã khách hàng sử dụng Iterator có thể không có quyền truy cập trực tiếp vào tập hợp mà nó đang lặp qua.
Mối quan hệ với các mẫu khác
- Bạn có thể sử dụng mẫu Iterator Pattern để lặp qua cây Composite Pattern.
- Bạn có thể kết hợp sử dụng mẫu Factory Method Pattern và Iterator Pattern để cho phép các lớp con của tập hợp trả về các loại Iterator khác nhau và đảm bảo rằng Iterator phù hợp với tập hợp.
- Bạn có thể kết hợp sử dụng mẫu Memento Pattern và Iterator Pattern để lưu trạng thái của Iterator hiện tại và khôi phục lại trạng thái đó khi cần thiết.
- Bạn có thể kết hợp sử dụng mẫu Visitor Pattern và Iterator Pattern để lặp qua cấu trúc dữ liệu phức tạp và thực hiện các hoạt động mong muốn trên các phần tử, ngay cả khi các phần tử thuộc về các lớp hoàn toàn khác nhau.