Card 07/ 08
Practice: Text Formatting Decorators in the Right Order
Trim, then upper-case, then wrap in brackets; build the stack that prints the expected line.
Text formatters are a natural Decorator, and this exercise asks you to build a stack and then predict a different one. Each formatter implements render() and holds another text. Plain(" hello ") renders its value unchanged, Trim strips spaces from both ends, Upper converts to capitals, and Brackets puts square brackets round the text.
- Build the stack that renders
"[HELLO]"fromPlain(" hello "). - Predict what
Trim(Brackets(Upper(Plain(" hello "))))renders, and say why.
Show a solution
from abc import ABC, abstractmethod
class Text(ABC):
@abstractmethod
def render(self) -> str: ...
class Plain(Text):
def __init__(self, value: str) -> None:
self._value = value
def render(self) -> str:
return self._value
class TextDecorator(Text):
def __init__(self, inner: Text) -> None:
self._inner = inner
class Trim(TextDecorator):
def render(self) -> str:
return self._inner.render().strip()
class Upper(TextDecorator):
def render(self) -> str:
return self._inner.render().upper()
class Brackets(TextDecorator):
def render(self) -> str:
return f"[{self._inner.render()}]"
source = Plain(" hello ")
print(repr(Brackets(Upper(Trim(source))).render()))
print(repr(Trim(Brackets(Upper(source))).render()))'[HELLO]'
'[ HELLO ]'| Layer | Receives | Returns |
|---|---|---|
| Plain | nothing | ' hello ' |
| Upper | ' hello ' | ' HELLO ' |
| Brackets | ' HELLO ' | '[ HELLO ]' |
| Trim | '[ HELLO ]' | '[ HELLO ]' |
The innermost decorator acts first on the way out, so Brackets(Upper(Trim(source))) trims, then capitalises, then brackets. In the reordered stack the trim is outermost and acts last, after the brackets are in place, so the spaces are inside the brackets and there is nothing at either end to strip.
← → move through sections and cards