cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 163 of 218
Ideas this builds on
Low-level design163 / 218

Decorator: wrap one extra behavior

Picture

A sender already works. We want to count successful sends without editing the sender or every caller.

Predict

If the inner sender fails, should a success counter increase?

Walk through the small example

No. Our wrapper increments only after a successful return.

Mental model and complete Python solution

A decorator preserves an interface and layers behavior around a collaborator. Wrappers can be composed, but their order matters: logging outside a retry wrapper sees one logical request, while logging inside it sees each attempt. This example deliberately counts accepted calls, not actual message delivery beyond the sender’s contract.

What the function promises: CountingSender exposes send and increments successes only when the wrapped sender returns normally.

class CountingSender:
    def __init__(self, inner):
        self.inner = inner
        self.successes = 0
    def send(self, message):
        self.inner.send(message)
        self.successes += 1

class LocalSender:
    def __init__(self):
        self.messages = []
    def send(self, message):
        if not message:
            raise ValueError("Empty message")
        self.messages.append(message)

wrapped = CountingSender(LocalSender())
wrapped.send("hello")
assert wrapped.successes == 1
try:
    wrapped.send("")
except ValueError:
    pass
assert wrapped.successes == 1

Work and storage: O(1) added work per wrapper; a stack of k wrappers adds O(k) call overhead.

When to recognize it: Counting after delegation records successes. Counting before it records attempts. Decide which metric you promised.

Check before applying it: Wrapper order affects observable behavior. Do not assume two decorators commute.

Change one rule

We want to avoid calling the sender on some requests by checking permissions first. Which neighboring idea fits?

See what changes

A protection proxy emphasizes controlling access. Decorator and proxy can look similar in code; distinguish their intent and contract.

Connect

Swap the rule, not the whole feature: A policy chooses behavior; a decorator surrounds existing behavior.

Proxy: control access to a helper: Compare adding behavior with controlling access to the underlying operation.