Skip to content

Commit df7a8eb

Browse files
committed
feat: implement Iterator pattern examples with various use cases
1 parent cfc138e commit df7a8eb

17 files changed

+1987
-0
lines changed
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
<div id="top"></div>
2+
3+
# Iterator Design Pattern
4+
5+
- A behavioral design pattern:
6+
- lets you (traverse elements || get a way to access the elements) of a collection without know its underlying representation (list, stack, tree, etc.).
7+
8+
- Identification:
9+
- Iterator is easy to recognize by the navigation methods (such as next, previous and others).
10+
- Client code that uses iterators might not have direct access to the collection being traversed.
11+
12+
<details>
13+
<summary> <h2 style="display: inline;"> Sections </h2> </summary>
14+
15+
- [Iterator Design Pattern](#iterator-design-pattern)
16+
- [Definitions](#definitions)
17+
- [Components \&\& Diagrams (UML class || Sequence diagrams).](#components--diagrams-uml-class--sequence-diagrams)
18+
- [Components By Guru](#components-by-guru)
19+
- [1. The Iterator interface:](#1-the-iterator-interface)
20+
- [2. Concrete Iterators implement:](#2-concrete-iterators-implement)
21+
- [3. The Collection (Container || Aggregation) interface:](#3-the-collection-container--aggregation-interface)
22+
- [4. Concrete Collections:](#4-concrete-collections)
23+
- [5. The Client:](#5-the-client)
24+
- [Components By geeksforgeeks](#components-by-geeksforgeeks)
25+
- [1. Iterator Interface/Abstract Class](#1-iterator-interfaceabstract-class)
26+
- [2. Concrete Iterator](#2-concrete-iterator)
27+
- [3. Aggregate Interface/Abstract Class](#3-aggregate-interfaceabstract-class)
28+
- [4. Concrete Aggregate](#4-concrete-aggregate)
29+
- [What problems can it solve || When to Use || Use Cases](#what-problems-can-it-solve--when-to-use--use-cases)
30+
- [Geeks: The Design Pattern can be useful in various scenarios, such as:](#geeks-the-design-pattern-can-be-useful-in-various-scenarios-such-as)
31+
- [GURU](#guru)
32+
- [Examples](#examples)
33+
- [Operations with context Example](#operations-with-context-example)
34+
- [Social Example \[Hard\]](#social-example-hard)
35+
- [When to **not** use Iterator Design Pattern](#when-to-not-use-iterator-design-pattern)
36+
- [Summery](#summery)
37+
- [Sources](#sources)
38+
</details>
39+
40+
41+
## Definitions
42+
43+
- <details>
44+
<summary> <h3 style="display: inline;"> Tutorial Point </h3> </summary>
45+
46+
- Used to get a way to access the elements of a collection object in sequential manner without any need to know its underlying representation.
47+
48+
</details>
49+
50+
- <details>
51+
<summary> <h3 style="display: inline;"> geeksforgeeks.org </h3> </summary>
52+
53+
- The Iterator pattern:
54+
- is a widely used design pattern in software development
55+
- that provides a way to access the elements of an aggregate object (such as a list or collection) sequentially without exposing its underlying representation
56+
57+
----
58+
59+
- It defines a separate object, called an iterator,
60+
- which encapsulates the details of traversing the elements of the aggregate,
61+
- allowing the aggregate to change its internal structure without affecting the way its elements are accessed.
62+
63+
</details>
64+
65+
66+
- <details>
67+
<summary> <h3 style="display: inline;"> refactoring.guru </h3> </summary>
68+
69+
`Iterator is a behavioral design pattern`
70+
- that allows sequential traversal through a complex data structure without exposing its internal details.
71+
72+
</details>
73+
74+
75+
## Components && Diagrams (UML class || Sequence diagrams).
76+
77+
### Components By Guru
78+
79+
<img style="background-color:#554777" src = "assets/iterator_guru_structure.png">
80+
81+
#### 1. The Iterator interface:
82+
- declares the operations required for traversing a collection:
83+
- fetching the next element,
84+
- retrieving the current position,
85+
- restarting iteration, etc.
86+
87+
#### 2. Concrete Iterators implement:
88+
- specific algorithms for traversing a collection.
89+
- The iterator object should track the traversal progress on its own.
90+
- This allows several iterators to traverse the same collection independently of each other.
91+
92+
#### 3. The Collection (Container || Aggregation) interface:
93+
- declares one or multiple methods for getting iterators compatible with the collection.
94+
- Note that:
95+
- the return type of the methods must be declared as the iterator interface so that the concrete collections can return various kinds of iterators.
96+
97+
#### 4. Concrete Collections:
98+
- return new instances of a particular concrete iterator class each time the client requests one.
99+
- You might be wondering, where’s the rest of the collection’s code? Don’t worry, it should be in the same class.
100+
- It’s just that these details aren’t crucial to the actual pattern, so we’re omitting them.
101+
102+
#### 5. The Client:
103+
- Works with both collections and iterators via their interfaces.
104+
- This way the client isn’t coupled to concrete classes,
105+
- allowing you to use various collections and iterators with the same client code.
106+
107+
- clients don’t create iterators on their own,
108+
- but instead get them from collections.
109+
- Yet, in certain cases, the client can create one directly; for example, when the client defines its own special iterator.
110+
111+
112+
### Components By geeksforgeeks
113+
114+
#### 1. Iterator Interface/Abstract Class
115+
- Defines the interface for accessing and traversing elements in the collection.
116+
- It typically includes methods like `hasNext()`, `next()`, and optionally `remove()`.
117+
118+
### 2. Concrete Iterator
119+
- Implements the Iterator interface and maintains the current position in the traversal of the aggregate.
120+
- It provides the actual implementation for the traversal operations defined in the Iterator interface.
121+
122+
123+
### 3. Aggregate Interface/Abstract Class
124+
- Defines the interface for creating an Iterator object.
125+
- It typically includes a method like `createIterator()` that returns an Iterator object for the collection.
126+
127+
### 4. Concrete Aggregate
128+
- Implements the Aggregate interface and represents the collection of objects.
129+
- It provides the implementation for creating an Iterator object that can traverse its elements.
130+
131+
## What problems can it solve || When to Use || Use Cases
132+
133+
- The Iterator pattern:
134+
- Allows us to access the elements of a collection sequentially without exposing its underlying representation.
135+
- It provides a way to iterate over a collection regardless of its internal structure.
136+
137+
138+
### Geeks: The Design Pattern can be useful in various scenarios, such as:
139+
140+
- **Need for sequential access**:
141+
- Use the Iterator pattern:
142+
- when you need to access elements of a collection sequentially without exposing its underlying representation.
143+
144+
- **Decoupling iteration logic**:
145+
- Use the Iterator pattern:
146+
- when you want to decouple the iteration logic from the collection.
147+
- This allows the collection to change its internal structure without affecting the way its elements are accessed.
148+
149+
- **Support for multiple iterators**:
150+
- Use the Iterator pattern:
151+
- when you need to support multiple iterators over the same collection.
152+
- Each iterator maintains its own iteration state, allowing multiple iterations to occur concurrently.
153+
154+
- **Simplifying client code**:
155+
- Use the Iterator pattern: to simplify client code that iterates over a collection.
156+
- Clients only need to interact with the iterator interface, abstracting away the complexity of the collection’s internal structure.
157+
158+
### GURU
159+
- Use the Iterator pattern when your collection has a complex data structure under the hood, but you want to hide its complexity from clients (either for convenience or security reasons).
160+
161+
- Use the pattern to reduce duplication of the traversal code across your app.
162+
163+
- Use the Iterator when you want your code to be able to traverse different data structures or when types of these structures are unknown beforehand.
164+
165+
## Examples
166+
167+
### Operations with context Example
168+
Source: [link](https://www.geeksforgeeks.org/iterator-pattern/)
169+
Dart Code: [link](salary_example.dart)
170+
171+
<img style="background-color:#554777" src = "assets/iterator_geeks.jpg">
172+
173+
174+
```dart
175+
176+
// Employee class
177+
class Employee {
178+
final String _name;
179+
final double _salary;
180+
181+
Employee(this._name, this._salary);
182+
183+
double getSalary() => _salary;
184+
String getName() => _name;
185+
}
186+
187+
/// Iterator interface
188+
abstract interface class Iterator<T> {
189+
bool hasNext();
190+
T next();
191+
}
192+
193+
/// Aggregate interface
194+
abstract interface class Aggregate<T> {
195+
Iterator<T> createIterator();
196+
}
197+
198+
/// Concrete Iterator
199+
class EmployeeIterator implements Iterator<Employee> {
200+
int _currentIndex = 0;
201+
final List<Employee> _employees;
202+
203+
EmployeeIterator(List<Employee> employees) : _employees = employees;
204+
205+
@override
206+
bool hasNext() {
207+
return _currentIndex < _employees.length;
208+
}
209+
210+
@override
211+
Employee next() {
212+
if (!hasNext()) {
213+
throw Exception("No such element");
214+
}
215+
return _employees[_currentIndex++];
216+
}
217+
}
218+
219+
// Concrete Aggregate
220+
class Company implements Aggregate<Employee> {
221+
final List<Employee> _employees;
222+
223+
Company(List<Employee> employees) : _employees = employees;
224+
225+
@override
226+
Iterator<Employee> createIterator() {
227+
return EmployeeIterator(_employees);
228+
}
229+
}
230+
231+
void main() {
232+
List<Employee> employees = [];
233+
employees.add(Employee("Alice", 50000));
234+
employees.add(Employee("Bob", 60000));
235+
employees.add(Employee("Charlie", 70000));
236+
237+
Company company = Company(employees);
238+
Iterator<Employee> iterator = company.createIterator();
239+
240+
double totalSalary = 0;
241+
while (iterator.hasNext()) {
242+
totalSalary += iterator.next().getSalary();
243+
}
244+
245+
print("Total salary: $totalSalary");
246+
}
247+
248+
/// Total salary: 180000.0
249+
250+
```
251+
252+
### Social Example [Hard]
253+
254+
- Source: [refactoring.guru java example](https://refactoring.guru/design-patterns/iterator/java/example)
255+
- Dart Code: [link](social_example.dart)
256+
257+
258+
## When to **not** use Iterator Design Pattern
259+
260+
1. **When the collection is not accessed sequentially**: If the collection is not accessed sequentially, using the Iterator pattern may add unnecessary complexity.
261+
2. **When the collection structure is fixed**: If the structure of the collection is fixed and unlikely to change, using the Iterator pattern may be overkill. Direct access methods may be more appropriate and simpler to implement.
262+
3. **When performance is critical**: In performance-critical applications, the overhead of using iterators may be significant, especially if the collection is large. In such cases, consider direct access methods for better performance.
263+
4. **When the language provides better alternatives**: Some languages provide built-in constructs or libraries that offer more efficient ways to iterate over collections.
264+
265+
266+
267+
268+
269+
## Summery
270+
271+
<img style="background-color:#554777" src = "assets/iterator_structure.png">
272+
273+
- The main idea of the Iterator pattern is to extract the traversal behavior of a collection into a separate object called an `iterator`.
274+
275+
276+
## Sources
277+
278+
- https://www.geeksforgeeks.org/iterator-pattern/
279+
- https://refactoring.guru/design-patterns/iterator
280+
- https://www.tutorialspoint.com/design_pattern/iterator_pattern.htm
281+
282+
283+
<p align="right">(<a href="#top">back to top</a>)</p>
Loading
Loading
Loading
Loading
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/// Iterator pattern is very commonly used design pattern in Java and .Net programming environment.
2+
/// This pattern is used to get a way to access the elements of a collection object in sequential manner without any need to know its underlying representation.
3+
library;
4+
5+
/// Implementation
6+
/// We're going to create a Iterator interface which narrates navigation method and a Container interface which returns the iterator.
7+
/// Concrete classes implementing the Container interface will be responsible to implement Iterator interface and use it
8+
9+
/// Step 1: Create interfaces.
10+
abstract interface class Iterator<T> {
11+
bool hasNext();
12+
T? next();
13+
}
14+
15+
abstract interface class Container<T> {
16+
Iterator getIterator();
17+
}
18+
19+
/// Step 2: Create concrete class implementing the Container interface.
20+
/// This class has inner class NameIterator implementing the Iterator interface.
21+
class NameRepository implements Container {
22+
@override
23+
Iterator getIterator() {
24+
return NameIterator();
25+
}
26+
}
27+
28+
class NameIterator implements Iterator {
29+
List<String> names = ["Robert", "John", "Julie", "Lora"];
30+
31+
int index = 0;
32+
33+
@override
34+
bool hasNext() {
35+
if (index < names.length) {
36+
return true;
37+
}
38+
return false;
39+
}
40+
41+
@override
42+
Object? next() {
43+
if (hasNext()) {
44+
return names[index++];
45+
}
46+
return null;
47+
}
48+
}
49+
50+
/// Step 3: Use the NameRepository to get iterator and print names.
51+
52+
void main() {
53+
NameRepository namesRepository = NameRepository();
54+
55+
for (Iterator iter = namesRepository.getIterator(); iter.hasNext();) {
56+
String name = iter.next();
57+
print("Name : $name");
58+
}
59+
}
60+
61+
62+
/// Step 4: Verify the output.
63+
64+
/// Name : Robert
65+
/// Name : John
66+
/// Name : Julie
67+
/// Name : Lora

0 commit comments

Comments
 (0)