Tôi đã tự hỏi điều gì làm cho Iterator trở nên đặc biệt khi so sánh với các cấu trúc tương tự khác, và điều đó khiến Gang of Four liệt kê nó như một mẫu thiết kế.
Iterator dựa trên tính đa hình (một hệ thống phân cấp của các bộ sưu tập có giao diện chung) và phân tách các mối quan tâm (lặp qua các bộ sưu tập nên độc lập với cách cấu trúc dữ liệu).
Nhưng điều gì sẽ xảy ra nếu chúng ta thay thế hệ thống phân cấp của các bộ sưu tập, ví dụ, hệ thống phân cấp của các đối tượng toán học (số nguyên, float, phức tạp, ma trận, v.v.) và iterator bằng một lớp biểu diễn một số hoạt động liên quan trên các đối tượng này, ví dụ như các hàm năng lượng. Sơ đồ lớp sẽ giống nhau.
Chúng ta có thể có thể tìm thấy nhiều ví dụ tương tự như Nhà văn, Họa sĩ, Trình mã hóa và có thể là những ví dụ tốt hơn, hoạt động theo cùng một cách. Tuy nhiên tôi chưa bao giờ nghe thấy bất kỳ thứ nào trong số này được gọi là Mẫu thiết kế.
Vậy điều gì làm cho Iterator trở nên đặc biệt?
Có phải thực tế là nó phức tạp hơn vì nó đòi hỏi trạng thái có thể thay đổi để lưu trữ vị trí hiện tại trong bộ sưu tập? Nhưng sau đó, trạng thái đột biến thường không được coi là mong muốn.
Để làm rõ quan điểm của tôi, hãy để tôi đưa ra một ví dụ chi tiết hơn.
Đây là vấn đề thiết kế của chúng tôi:
Giả sử chúng ta có một hệ thống phân cấp các lớp và một hoạt động được xác định trên các đối tượng của các lớp này. Giao diện của hoạt động này là giống nhau cho mỗi lớp, nhưng việc triển khai có thể hoàn toàn khác nhau. Người ta cũng cho rằng nên áp dụng thao tác nhiều lần trên cùng một đối tượng, với các tham số khác nhau.
Đây là một giải pháp hợp lý cho vấn đề thiết kế của chúng tôi (thực tế là khái quát hóa mẫu lặp):
Để phân tách các mối quan tâm, không nên thêm các cài đặt của hoạt động như các hàm vào hệ thống phân cấp lớp ban đầu (các đối tượng toán hạng). Vì chúng ta muốn áp dụng thao tác nhiều lần trên cùng một toán hạng, nên nó được biểu diễn bằng một đối tượng giữ tham chiếu đến toán hạng, không chỉ bởi một hàm. Do đó, đối tượng toán hạng sẽ cung cấp một hàm trả về đối tượng đại diện cho hoạt động. Đối tượng này cung cấp một chức năng thực hiện các hoạt động thực tế.
Một ví dụ:
Có một lớp cơ sở hoặc giao diện MathObject
(tên ngu ngốc, tôi biết, có lẽ ai đó có ý tưởng tốt hơn.) Với các lớp dẫn xuất MyInteger
và MyMatrix
. Đối với mỗi MathObject
thao tác Power
nên được xác định cho phép tính toán hình vuông, hình khối, v.v. Vì vậy, chúng tôi có thể viết (bằng Java):
MathObject i = new MyInteger(5);
Power powerOfFive = i.getPower();
MyInteger square = powerOfFive.calculate(2); // should return 25
MyInteger cube = powerOfFive.calculate(3); // should return 125