Skip to content

Commit 88fe948

Browse files
committed
🔧 Adding
Iterator Pattern
1 parent d989908 commit 88fe948

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
from abc import ABC, abstractmethod
2+
from typing import List
3+
4+
# --------- Profile class (represents a user in the network) ----------
5+
class Profile:
6+
def __init__(self, profile_id: str, name: str, email: str, company: str, friends: List[str]):
7+
self.id = profile_id
8+
self.name = name
9+
self.email = email
10+
self.company = company
11+
self.friends = friends
12+
13+
def __repr__(self):
14+
return f"{self.name} ({self.email})"
15+
16+
17+
# --------- Iterator Interface ----------
18+
class ProfileIterator(ABC):
19+
@abstractmethod
20+
def has_more(self) -> bool:
21+
pass
22+
23+
@abstractmethod
24+
def get_next(self) -> Profile:
25+
pass
26+
27+
28+
# --------- Concrete Iterator ----------
29+
class FacebookIterator(ProfileIterator):
30+
def __init__(self, facebook, profile_id: str, type_: str):
31+
self.facebook = facebook
32+
self.profile_id = profile_id
33+
self.type = type_ # "friends" or "coworkers"
34+
self.current_position = 0
35+
self.cache = []
36+
self._lazy_load()
37+
38+
def _lazy_load(self):
39+
profile = self.facebook.find_profile_by_id(self.profile_id)
40+
if not profile:
41+
return
42+
43+
if self.type == "friends":
44+
self.cache = self.facebook.get_profiles(profile.friends)
45+
elif self.type == "coworkers":
46+
all_friends = self.facebook.get_profiles(profile.friends)
47+
self.cache = [p for p in all_friends if p.company == profile.company]
48+
49+
def has_more(self) -> bool:
50+
return self.current_position < len(self.cache)
51+
52+
def get_next(self) -> Profile:
53+
if self.has_more():
54+
profile = self.cache[self.current_position]
55+
self.current_position += 1
56+
return profile
57+
return None
58+
59+
60+
# --------- Collection Interface ----------
61+
class SocialNetwork(ABC):
62+
@abstractmethod
63+
def create_friends_iterator(self, profile_id: str) -> ProfileIterator:
64+
pass
65+
66+
@abstractmethod
67+
def create_coworkers_iterator(self, profile_id: str) -> ProfileIterator:
68+
pass
69+
70+
71+
# --------- Concrete Collection ----------
72+
class Facebook(SocialNetwork):
73+
def __init__(self, profiles: List[Profile]):
74+
self.profiles = {p.id: p for p in profiles}
75+
76+
def find_profile_by_id(self, profile_id: str) -> Profile:
77+
return self.profiles.get(profile_id)
78+
79+
def get_profiles(self, ids: List[str]) -> List[Profile]:
80+
return [self.profiles[id_] for id_ in ids if id_ in self.profiles]
81+
82+
def create_friends_iterator(self, profile_id: str) -> ProfileIterator:
83+
return FacebookIterator(self, profile_id, "friends")
84+
85+
def create_coworkers_iterator(self, profile_id: str) -> ProfileIterator:
86+
return FacebookIterator(self, profile_id, "coworkers")
87+
88+
89+
# --------- Client Code (Spammer) ----------
90+
class SocialSpammer:
91+
def send(self, iterator: ProfileIterator, message: str):
92+
while iterator.has_more():
93+
profile = iterator.get_next()
94+
print(f"Sending '{message}' to {profile.email}")
95+
96+
97+
# --------- Application Setup ----------
98+
def main():
99+
# Sample Data
100+
profiles = [
101+
Profile("1", "Alice", "[email protected]", "ABC Corp", ["2", "3"]),
102+
Profile("2", "Bob", "[email protected]", "ABC Corp", ["1"]),
103+
Profile("3", "Charlie", "[email protected]", "XYZ Ltd", ["1"]),
104+
Profile("4", "David", "[email protected]", "ABC Corp", ["1", "2"]),
105+
]
106+
107+
facebook = Facebook(profiles)
108+
spammer = SocialSpammer()
109+
110+
print("Send spam to friends of Alice:\n")
111+
friends_iterator = facebook.create_friends_iterator("1")
112+
spammer.send(friends_iterator, "Hi! This is a spam message.")
113+
114+
print("\nSend spam to coworkers of Alice:\n")
115+
coworkers_iterator = facebook.create_coworkers_iterator("1")
116+
spammer.send(coworkers_iterator, "Meeting at 3PM today!")
117+
118+
119+
if __name__ == "__main__":
120+
main()

0 commit comments

Comments
 (0)