Exercise 3: Why Decorator and Composite Solve Genuinely Different Problems — Possible Solution ==================================================================== WHAT DECORATOR ACTUALLY GUARANTEES ------------------------------ This chapter verified Decorator's core guarantee directly: wrapping SimpleCoffee in MilkDecorator then SugarDecorator produced a NEW object whose cost() and description() combine the base with each added layer (2.00 -> 2.50 -> 2.80) - and afterward, the ORIGINAL base object still reported 'Coffee' / 2.00, completely unmodified. A second, separate chain (WhipDecorator wrapping that same base) produced a genuinely different result (2.75) that didn't interfere with the first chain at all. Decorator's job is ADDING BEHAVIOR to a single object, one optional layer at a time, without touching the object underneath. WHAT COMPOSITE ACTUALLY GUARANTEES ------------------------------ This chapter verified Composite's core guarantee directly: calling .get_size() on a single File, on a whole nested Directory tree, and on a smaller Directory partway down that tree all worked through the exact same one-line call, with the correct total (285, matching a manual calculation) computed automatically regardless of how deep the tree went. Composite's job is letting a caller treat ONE OBJECT AND A WHOLE GROUP OF OBJECTS the same way, without the caller needing to know or care which one it's dealing with. WHY BOTH INVOLVE "ONE OBJECT HOLDING A REFERENCE TO ANOTHER" BUT SOLVE DIFFERENT PROBLEMS ------------------------------ Structurally, both patterns involve an object wrapping or containing another object - which is why they can look similar at a glance. But the actual problem each one verified solving is different: - Decorator answers: "how do I add optional extra behavior to ONE object, layer by layer, without modifying its class?" There is always exactly one underlying object being progressively wrapped, and each layer's whole purpose is to CHANGE what cost()/ description() report by adding something new. - Composite answers: "how do I let calling code treat a SINGLE item and a WHOLE TREE of items identically?" A Directory's children aren't optional add-on layers changing one object's behavior - they're a genuine collection of peer objects (some leaves, some themselves collections), and get_size() doesn't add new behavior on top of anything; it recursively delegates to whatever's already there. A concrete tell: stacking more Decorators changes what the SAME underlying beverage's cost/description reports (2.00 -> 2.50 -> 2.80). Adding more children to a Directory doesn't change any existing file's own size at all - it just changes how many things get summed together. One pattern modifies what a single wrapped thing reports; the other aggregates over a genuinely plural structure. WHY THIS WORKS AS AN ANSWER ------------------------------ The answer grounds both patterns in this chapter's own verified results rather than restating their definitions abstractly, and identifies a concrete, checkable distinction (whether stacking more wrappers changes one object's own reported values, vs. whether adding more children changes what's being aggregated) rather than only asserting the two patterns are different.