I. Giới thiệu:
Iterator là một Design Pattern thuộc loại Behavior. Nó cho phép chúng ta duyệt các phần tử của một collection mà không để lộ các implement chi tiết của nó. Iterator Pattern gồm các thành phần chính như sau:
IterableProtocol
trong Swift định nghĩa kiểu dữ liệu cho phép truy xuất các phần tử thông qua vòng lặpfor
.- Iterator Object: Object được custom để có thể truy xuất dữ liệu theo kiểu vòng lặp.
II. Cách thức hoạt động:
Iterator Pattern cung cấp cách truy xuất tuần tự vào các phần tử của một collection. Cách truy xuất này sẽ được chúng ta quyết định tùy thuộc vào cấu trúc dữ liệu của collection. Cấu trúc dữ liệu có thể là Array, Tree,… Đồng thời, cách truy xuất dữ liệu của nó sẽ được che giấu đi và không để lộ ra bên ngoài.
III. Iterator Pattern được sử dụng khi nào?
Iterator Pattern được sử dụng khi có một lớp hoặc cấu trúc chứa một nhóm các đối tượng được sắp xếp và muốn truy xuất phần tử bằng cách sử dụng vòng lặp for
.
IV. Ví dụ:
Để dễ tiếp cận và hiểu rõ hơn, chúng ta sẽ xử dụng cấu trúc dữ liệu Queue để làm một ví dụ về Iterator Pattern. Queue trong ví dụ sẽ đóng vai trò là Iterator Object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword">public</span> <span class="token keyword">struct</span> <span class="token builtin">Queue</span><span class="token operator"><</span>T<span class="token operator">></span> <span class="token punctuation">{</span> fileprivate <span class="token keyword">var</span> array <span class="token operator">=</span> <span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">public</span> <span class="token keyword">var</span> <span class="token builtin">isEmpty</span><span class="token punctuation">:</span> <span class="token builtin">Bool</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> array<span class="token punctuation">.</span><span class="token builtin">isEmpty</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">var</span> <span class="token builtin">count</span><span class="token punctuation">:</span> <span class="token builtin">Int</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> array<span class="token punctuation">.</span><span class="token builtin">count</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function">enqueue</span><span class="token punctuation">(</span><span class="token number">_</span> element<span class="token punctuation">:</span> T<span class="token punctuation">)</span> <span class="token punctuation">{</span> array<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function">dequeue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> T<span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token builtin">isEmpty</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> array<span class="token punctuation">.</span><span class="token function">removeFirst</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Thực hiện adopt Sequence
protocol để đưa Queue thành dạng Iterator.
1 2 3 4 5 6 | <span class="token keyword">extension</span> <span class="token builtin">Queue</span><span class="token punctuation">:</span> <span class="token builtin">Sequence</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">func</span> <span class="token function">makeIterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">IndexingIterator</span><span class="token operator"><</span><span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> array<span class="token punctuation">.</span><span class="token function">makeIterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Thêm các phần tử vào Queue.
1 2 3 4 5 | <span class="token keyword">var</span> queue <span class="token operator">=</span> <span class="token builtin">Queue</span><span class="token operator"><</span><span class="token builtin">String</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span> queue<span class="token punctuation">.</span><span class="token function">enqueue</span><span class="token punctuation">(</span><span class="token string">"Element 1"</span><span class="token punctuation">)</span> queue<span class="token punctuation">.</span><span class="token function">enqueue</span><span class="token punctuation">(</span><span class="token string">"Element 2"</span><span class="token punctuation">)</span> queue<span class="token punctuation">.</span><span class="token function">enqueue</span><span class="token punctuation">(</span><span class="token string">"Element 3"</span><span class="token punctuation">)</span> |
Truy xuất phần tử trong Queue
1 2 3 4 | <span class="token keyword">for</span> element <span class="token keyword">in</span> queue <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
V. Tài liệu tham khảo:
- Design Pattern by Tutorials – Raywenderlich
- State Pattern by refactoring.guru