The before code shows a Car tightly coupled to an Engine it creates internally, making reuse and testing harder. The after code shows association where Vehicle references a Driver without owning it, aggregation where Team contains members that can exist independently, and composition where House creates and owns Room objects, controlling their lifetime.
### Before: No clear relationship, tight coupling and unclear ownership
class Engine:
def __init__(self):
self.status = 'off'
class Car:
def __init__(self):
self.engine = Engine() # tightly coupled
car = Car()
print(car.engine.status)
### After: Clear relationships
# Association example
class Driver:
def __init__(self, name):
self.name = name
class Vehicle:
def __init__(self):
self.driver = None # association: vehicle knows driver but does not own
vehicle = Vehicle()
driver = Driver('Alice')
vehicle.driver = driver
# Aggregation example
class Team:
def __init__(self):
self.members = [] # aggregation: members can exist independently
def add_member(self, member):
self.members.append(member)
team = Team()
member1 = Driver('Bob')
team.add_member(member1)
# Composition example
class Room:
def __init__(self):
self.lights_on = False
class House:
def __init__(self):
self.rooms = [Room() for _ in range(3)] # composition: house owns rooms
house = House()
print(len(house.rooms))