
Every export format changes the same method. The PDF branch checks permissions one way; the CSV branch reloads the data. You decide to apply Strategy before identifying which behavior should vary and which should stay unchanged. The pattern may merely spread the confusion across more files.
Design Patterns deserves attention because it provides vocabulary for discussing those decisions. I recommend using the catalog against a concrete change, comparing intent and consequences with a simple alternative. Recognizing collaboration matters more than producing an impressive number of classes with familiar names.
Design Patterns: Elements of Reusable Object-Oriented Software is by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, known as the Gang of Four. Addison-Wesley/Pearson's listing records first-edition publication on October 31, 1994, and a 1995 copyright. Its catalog contains 23 patterns, with C++ and Smalltalk examples.
The date matters because readers often associate the book directly with Java. Translate mechanisms into your language and recognize what its libraries already provide. You are studying recurring ways to organize responsibilities; their expression through files, classes or functions can differ.
In a retrospective interview with the authors, consistent descriptions are discussed as a way to demand completeness, including consequences and known uses. That care helps avoid reading the book as a collection of diagrams.
Start with intent: which problem does the collaboration address? Examine applicability, participants and consequences. Recognizing the diagram's shape cannot establish whether the pattern helps in your context. Similar structures may exist for different reasons.
For our exporter, the question is varying representation while retaining access and data-selection decisions. If the actual problem is a slow query, replacing conditionals with classes misses the cause. A useful problem statement should survive removal of the pattern's name.
This hypothetical exercise includes no implementation or generated files. An authorized user requests a two-invoice report. The workflow retrieves one snapshot, ordered by identifier, and passes it to the selected representation. The formatter receives no credentials and repeats no query.
| Record | Amount in integer BRL cents |
|---|---|
A-1 | 1500 |
A-2 | 2500 |
The shared contract preserves identifiers, amounts and order. CSV uses UTF-8, comma separators, a fixed header and LF line endings, including the final one. For these controlled inputs, the expected representation is:
id,amount_cents
A-1,1500
A-2,2500
PDF presents the same invoices as R$ 15,00 and R$ 25,00, totaling R$ 40,00. This is a semantic presentation expectation rather than sample PDF bytes. Fonts, pagination and rendering would still need checks against the actual generator.
Reject unknown formats before querying data. Missing required fields should produce an explicit error rather than a partial file presented as success. Define empty-report behavior and volume limits too. Two functions sharing a signature may disagree on these behaviors and fail to be interchangeable for their caller.
The result can contain content bytes, a media type and a filename. Use text/csv for CSV and application/pdf for PDF. Delivery code then selects HTTP headers from that metadata rather than rediscovering the selected format. A test can detect valid content being delivered under the wrong extension or media type. This checks a common promise at the application boundary without mistakenly demanding identical bytes from fundamentally different document representations. Keep those distinctions visible when reviewing the shared exporter contract.
Free and paid products to turn ideas into a foundation you can actually ship.
13 products availableContinue exploring similar topics

Apply Michael Nygard's approach to timeouts, isolation and recovery through a controlled failure exercise.

Turn passive study into a learning project with direct practice, feedback and spaced retrieval.

Critical review of Rob Fitzpatrick: investigate real episodes, separate facts from hypotheses and do not mistake interviews for market validation.
A 47-point checklist to find bugs, security risks, and performance issues before launch.
Production-tested templates trusted by developers. Save weeks of setup on your next project.
Strategy organizes alternative behaviors used by a context through a common contract. Here, the variation is representing a snapshot as CSV or PDF. A mapping from format names to functions can fill that role. The workflow chooses a function, supplies records and receives content plus media type.
An abstract class and factory need not come first. Small functions and two explicit branches may be clearer. Costs change when representations gain their own configuration, dependencies or independent maintenance. Receiving an exporter object may then make collaboration easier to follow.
Selection still exists somewhere, usually where the operation is assembled. The benefit is concentrating it and preventing format from determining unrelated authorization, query and delivery paths. Adding an alternative does not mean no existing file changes: its registration point may need editing.
In Erich Gamma's discussion of design principles, he connects interfaces with dependency management and discusses favoring composition over inheritance. Collaboration should allow implementation to vary without attaching clients to unnecessary details.
Our report service receives the chosen exporter. It inherits from neither CsvReport nor PdfReport. Composition lets representation change without redefining the workflow. If a PDF library requires subclasses for an extension point, evaluate that requirement inside the adapter while preserving a clear boundary for the application.
Avoid interpreting interface as an obligation to use a language's interface construct. A function with an explicit contract may suffice. What must remain stable is the promised collaboration, including errors and external effects, rather than merely a method list.
Suppose the PDF vendor requires HTML and returns a task identifier while the application expects completed content. An Adapter can translate that interface into the report's expected form. It prepares input, follows completion according to the vendor contract and turns failures into outcomes the caller understands.
That differs from selecting CSV or PDF. Strategy expresses alternative representations; Adapter addresses interface incompatibility with a participant. One design may use both ideas, but they answer different questions. Changing PDF vendors should affect translation without changing authorized record selection.
If the vendor only completes asynchronously, pretending every request is instantaneous creates false expectations. The contract may need a deadline or a report-preparing state. Naming something Adapter cannot remove that cost or make different failure modes and execution times equivalent.
Our workflow has one requester waiting for a result. There is no requirement to notify multiple interested parties about report changes. An explicit call organizes retrieval, representation and response without subscriptions or registration rules.
Observer becomes relevant for notification between a subject and its observers. Adding it because export has several stages creates new questions: who subscribes, when do they unsubscribe, in which order do callbacks run and what happens on failure? Maintaining those answers needs a requirement to justify the expense.
A distributed broker is not automatically an equivalent implementation of Observer. Persistence, repeated delivery and separate processes introduce another set of choices. The catalog helps name responsibility relationships without independently supplying a messaging contract.
Use the two records to compare the current and proposed designs. Check exact CSV output, semantic PDF content and preserved order. Verify one data-selection operation per request and that the formatter cannot expand the user's authorized access.
Then add a plain-text representation: A-1: 1500 BRL cents and A-2: 2500 BRL cents, in that order. Observe whether editing authorization is necessary or whether only implementation and registration change. This text is another teaching expectation, not an artifact generated by this review.
Count reading effort too. If understanding a header once required one method and now requires navigating eight files, identify which benefit pays for that expense. An abstraction improves a design when it eases a relevant change without hiding important decisions.
The C++ and Smalltalk setting should not become an obligation to copy structures into other languages. First-class functions can replace parts of a hierarchy used to vary behavior. This preserves the design question while potentially reducing the mechanism required to answer it.
In the retrospective interview, the authors acknowledge that some languages offer alternative solutions to catalog problems. Avoid learning a solution and searching for places to install it. First consider capabilities already present in the language, rendering library or framework.
A local collaboration is also not a complete production solution. Our exercise establishes no large-volume export, cancellation, PDF accessibility or reader compatibility. If CSV later accepts arbitrary text, define escaping and consumer interpretation. Those are product contracts that selecting Strategy cannot settle.
I recommend it to developers who understand objects, polymorphism and dependencies and can relate an example to maintained code. Beginners without that foundation may memorize names without recognizing the problems. First building two simple exporter versions can reveal where a change spreads.
Fowler's Refactoring helps move between structures while preserving behavior. Ousterhout's A Philosophy of Software Design offers a lens on complexity that interfaces hide or spread. Clean Code complements discussion of local readability.
Prioritize the catalog when recognizing library collaborations or justifying recurring variation. For a short script with two stable formats, a simple solution may last a long time. Understanding a pattern includes knowing why its full implementation would be excessive there.
Choose an existing source of change. Read two candidates' intents, examine consequences and write the alternative without an explicit pattern. Only then compare structures and examples. Record what varies, who selects the alternative and which promises the client needs preserved.
Make a small change and ask someone else to follow a call to its result. If they can explain the collaboration and introduced cost, the vocabulary helps. If accepting the design depends on recognizing abbreviations, return to the original problem.
I recommend Design Patterns as a catalog of reusable decisions. Its contribution appears when a name shortens a precise conversation about responsibilities and consequences. Understand the variation and pay only for flexibility needed by the code you actually have.