Skip to content

Commit 8063f34

Browse files
committed
Update Observer
1 parent 78d4faf commit 8063f34

File tree

8 files changed

+125
-0
lines changed

8 files changed

+125
-0
lines changed

patterns/behavioural/observer/solution_04/__init__.py

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .customer import Customer
2+
3+
__all__ = ["Customer"]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from dataclasses import dataclass, field
2+
from typing import List, Set
3+
4+
from ..product import Product
5+
6+
7+
@dataclass
8+
class Customer:
9+
name: str
10+
interests: List[Product]
11+
satisfied: bool = False
12+
own_products: Set[Product] = field(default_factory=set)
13+
14+
def __call__(self, product: Product) -> None:
15+
if product not in self.interests:
16+
print(f"I'm {self.name} and I am not interested in {product.name}")
17+
return
18+
19+
print(f"I'm {self.name} and I bought a {product.name}")
20+
self.own_products.add(product)
21+
self.satisfied = all(product in self.own_products for product in self.interests)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import time
2+
from .customer import Customer
3+
from .product import Product
4+
from .store import Store
5+
6+
7+
def main() -> None:
8+
cellphone = Product("MobileX", "TechS", 300)
9+
couch = Product("GiantSofa", "AllComfort", 800)
10+
mug = Product("CoffeeM", "IndustrialTea", 20)
11+
12+
customers = [
13+
Customer(name="John", interests=[cellphone]),
14+
Customer(name="Mary", interests=[couch, mug]),
15+
Customer(name="Alicia", interests=[cellphone, mug]),
16+
]
17+
18+
store = Store(name="AllYouNeed")
19+
20+
for customer in customers:
21+
store.subscribe(customer, customer.interests)
22+
23+
late_customer = Customer(name="bob", interests=[cellphone, couch, mug])
24+
late_customer_arrival = 3
25+
26+
customers.append(late_customer)
27+
28+
initial_time = time.time()
29+
30+
products = [cellphone, couch, mug]
31+
estimated_time_arrivals = [1, 2, 4]
32+
33+
while True:
34+
current_time = time.time() - initial_time
35+
36+
for product, eta in zip(products, estimated_time_arrivals):
37+
if current_time >= eta and product not in store.products:
38+
store.add_product(product)
39+
40+
if current_time >= late_customer_arrival and not store.is_subscribed(late_customer):
41+
store.subscribe(late_customer, late_customer.interests)
42+
43+
if all(customer.satisfied for customer in customers):
44+
break
45+
46+
time.sleep(0.05) # To avoid blocking CPU
47+
48+
49+
if __name__ == "__main__":
50+
main()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .product import Product
2+
3+
__all__ = ["Product"]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from typing import NamedTuple
2+
3+
4+
class Product(NamedTuple):
5+
name: str
6+
brand: str
7+
price: float
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .store import Store
2+
3+
__all__ = ["Store"]
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from asyncio import Protocol
2+
from dataclasses import dataclass, field
3+
from typing import Callable, Dict, List, Set
4+
from collections import defaultdict
5+
6+
from ..product import Product
7+
8+
9+
NOTIFY_FUNCTION = Callable[[Product], None]
10+
11+
12+
@dataclass
13+
class Store:
14+
name: str
15+
products: Set[Product] = field(default_factory=set)
16+
product_notifiers: Dict[Product, List[NOTIFY_FUNCTION]] = field(
17+
default_factory=lambda: defaultdict(list)
18+
)
19+
20+
def subscribe(
21+
self, notifier: NOTIFY_FUNCTION, relevant_products: List[Product]
22+
) -> None:
23+
for product in relevant_products:
24+
self.product_notifiers[product].append(notifier)
25+
if product in self.products:
26+
notifier(product)
27+
28+
def is_subscribed(self, notifier: NOTIFY_FUNCTION) -> bool:
29+
all_notifiers: List[NOTIFY_FUNCTION] = sum(self.product_notifiers.values(), [])
30+
return notifier in all_notifiers
31+
32+
def add_product(self, product: Product) -> None:
33+
self.products.add(product)
34+
self.notify(product)
35+
36+
def notify(self, product: Product) -> None:
37+
for notifier in self.product_notifiers[product]:
38+
notifier(product)

0 commit comments

Comments
 (0)