Inversion of control makes software easier to extend by transferring dependency creation or behavior control from a class to its caller. Instead of constructing its own parts, a class receives objects it can use. This reduces rigid dependencies and lets existing code accommodate changing requirements. section 7.2.1 section 7.4
Swapping a bicycle frame
A rigid Bicycle creates its own Tire and Frame objects, so changing the frame requires editing Bicycle. Passing front_tire, back_tire, and frame into Bicycle lets the caller choose the implementations. A CarbonFiberFrame can then replace Frame without changing Bicycle, provided it offers the expected methods and attributes. section 7.2.1
Use inversion of control to:
- Customize behavior without modifying low-level implementation. section 7.4
- Replace real dependencies with test doubles to isolate class behavior. section 7.2.1
- Extend application behavior with focused commands, such as preserving GitHub star timestamps. section 7.3
Listing 7.5. Using inversion of control
class Tire:
def __repr__(self):
return 'A rubber tire'
class Frame:
def __repr__(self):
return 'An aluminum frame'
class Bicycle:
def __init__(self, front_tire, back_tire, frame): #1
self.front_tire = front_tire
self.back_tire = back_tire
self.frame = frame
def print_specs(self):
print(f'Frame: {self.frame}')
print(f'Front tire: {self.front_tire}, back tire: {self.back_tire}')
if __name__ == '__main__':
bike = Bicycle(Tire(), Tire(), Frame()) #2
bike.print_specs()
Inspect the compact Python example that passes dependencies into Bicycle rather than constructing them internally. section 7.2.1


