Notes and exercises for learning design patterns
You are building a reporting dashboard. The sidebar shows a list of available reports — title and author — fetched on every page load.
Each report is generated by a RealReportService. Generating a report is
expensive: it involves reading from a database, assembling a PDF, and can take
several seconds. Only one or two reports are actually downloaded per session,
but the current code creates a RealReportService for every report in the
list. Most of those reports are generated and then thrown away unread.
Your task is to fix this with a virtual proxy.
Open exercise1.py and implement LazyReportProxy.
The proxy must:
RealReportService
(report_id, title, author).RealReportService in __init__.get_metadata() without creating a RealReportService.
You have everything you need from the constructor arguments.get_content() so that it creates the RealReportService on
the first call and delegates to it. On subsequent calls it reuses the
same instance.RealReportService anywhere a ReportService
is expected.class ReportService(ABC):
def get_metadata(self) -> ReportMetadata: ...
def get_content(self) -> str: ...
pytest exercise1.py -v
report_id, title, and author as instance attributes in
__init__. You can build a ReportMetadata from them without touching
the real service._load() is:def _load(self):
if self._real is None:
self._real = RealReportService(...)
return self._real
self._load() first.
Methods that do not need it skip the call entirely.Run the tests and observe the output. The [RealReportService] Generating...
message should only appear when get_content() is called, not when
get_metadata() is called. If you create fifty proxies and only request
content from one, only one generation message appears.