liveBook · Manning

Decorator design pattern

As explained in Software Design for Python Programmers

The Decorator Design Pattern is a structural design pattern that dynamically attaches additional responsibilities to an object by wrapping it with objects that share its interface.

The Decorator Design Pattern adds responsibilities to an object at run time by wrapping it with objects that share its interface. It provides a flexible alternative to hardcoding every variation into the original class. section 14.0 section 14.3

A ticket class that stores party access, VIP seating, and drink coupons as attributes must know every enhancement and calculate each one explicitly. Adding, removing, or changing an enhancement therefore requires modifying Ticket and can create change leaks. section 14.3.2

The refactored design makes BaseTicket and every enhancement a Ticket. Enhancement stores another Ticket, and its cost is its own price plus the wrapped ticket’s cost. Party, VIP, and Coupon can therefore be chained in any order while client code treats the result as a ticket. section 14.3.3

Building an enhanced ticket

Start with BaseTicket(), then wrap it successively: Party(ticket), VIP(ticket), Coupon(ticket), and Coupon(ticket). Calling cost on the outermost object traverses the chain and produces the combined total. A different chain can add three coupons and party access without changing Ticket or the decorators.

Figure 14.12 The generic model of the Decorator Design Pattern. Compare with figure 14.11. A ConcreteComponent object by itself is a Component. A ConcreteComponent wrapped by Decorator objects is also a Component. The private component instance variable of superclass Decorator is either a ConcreteComponent object or a Decorator object. This chain implements the nested wrapping of the Decorator objects.
A diagram of a component

AI-generated content may be incorrect.

Use the generic model to map Component, ConcreteComponent, Decorator, and ConcreteDecorator roles onto a wrapping architecture. section 14.3.4

How Software Design for Python Programmers covers it

How deep it goes
Explains the pattern through a flawed ticket design, wrapper classes, recursive cost delegation, and a generic role mapping.
Examples
Uses base tickets, pregame parties, VIP seating, and repeated drink coupons to demonstrate inflexible attributes and flexible wrapper chains.
What it assumes
Assumes familiarity with class responsibilities, instance variables, methods, inheritance, and aggregation while distinguishing the pattern from Python decorators.
What you can do after
Build it from scratch by defining a shared component, a wrapper holding that component, and decorators that extend delegated behavior.
How it connects
Connects runtime responsibilities with inheritance, aggregation, abstract classes, subclassing, and object composition.

Also explained in

Compare how 2 books explain decorator design pattern →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Software Design for Python Programmers. The section links point to the parts of the book it draws on.