|
| 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