class StandardPricing:
def price(self, daily_cents, days):
return daily_cents * days
class StudentPricing:
"""20% off with a valid student card."""
def price(self, daily_cents, days):
return daily_cents * days * 80 // 100
class WeeklyPricing:
"""Each full week costs 5 days; extra days are at the normal rate."""
def price(self, daily_cents, days):
weeks, extra = divmod(days, 7)
return daily_cents * (weeks * 5 + extra)
class Rental:
def __init__(self, item_name, daily_cents, days, pricing):
self.item_name = item_name
self.daily_cents = daily_cents
self.days = days
self.pricing = pricing # composition: a Rental HAS a pricing policy
def cost(self):
return self.pricing.price(self.daily_cents, self.days) # delegation
orders = [Rental("skis", 3500, 3, StandardPricing()),
Rental("skis", 3500, 3, StudentPricing()),
Rental("snowboard", 4000, 9, WeeklyPricing())]
for r in orders:
print(f"{r.item_name:<10}{type(r.pricing).__name__:<16}${r.cost() / 100:.2f}")
orders[0].pricing = StudentPricing() # change behaviour at run time
print(orders[0].cost())
pricing.py: composition and delegation with three interchangeable strategies.