@booklib/skills 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/animation-at-work/SKILL.md +246 -0
  4. package/animation-at-work/assets/example_asset.txt +1 -0
  5. package/animation-at-work/references/api_reference.md +369 -0
  6. package/animation-at-work/references/review-checklist.md +79 -0
  7. package/animation-at-work/scripts/example.py +1 -0
  8. package/bin/skills.js +85 -0
  9. package/clean-code-reviewer/SKILL.md +292 -0
  10. package/clean-code-reviewer/evals/evals.json +67 -0
  11. package/data-intensive-patterns/SKILL.md +204 -0
  12. package/data-intensive-patterns/assets/example_asset.txt +1 -0
  13. package/data-intensive-patterns/references/api_reference.md +34 -0
  14. package/data-intensive-patterns/references/patterns-catalog.md +551 -0
  15. package/data-intensive-patterns/references/review-checklist.md +193 -0
  16. package/data-intensive-patterns/scripts/example.py +1 -0
  17. package/data-pipelines/SKILL.md +252 -0
  18. package/data-pipelines/assets/example_asset.txt +1 -0
  19. package/data-pipelines/references/api_reference.md +301 -0
  20. package/data-pipelines/references/review-checklist.md +181 -0
  21. package/data-pipelines/scripts/example.py +1 -0
  22. package/design-patterns/SKILL.md +245 -0
  23. package/design-patterns/assets/example_asset.txt +1 -0
  24. package/design-patterns/references/api_reference.md +1 -0
  25. package/design-patterns/references/patterns-catalog.md +726 -0
  26. package/design-patterns/references/review-checklist.md +173 -0
  27. package/design-patterns/scripts/example.py +1 -0
  28. package/domain-driven-design/SKILL.md +221 -0
  29. package/domain-driven-design/assets/example_asset.txt +1 -0
  30. package/domain-driven-design/references/api_reference.md +1 -0
  31. package/domain-driven-design/references/patterns-catalog.md +545 -0
  32. package/domain-driven-design/references/review-checklist.md +158 -0
  33. package/domain-driven-design/scripts/example.py +1 -0
  34. package/effective-java/SKILL.md +195 -0
  35. package/effective-java/assets/example_asset.txt +1 -0
  36. package/effective-java/references/api_reference.md +1 -0
  37. package/effective-java/references/items-catalog.md +955 -0
  38. package/effective-java/references/review-checklist.md +216 -0
  39. package/effective-java/scripts/example.py +1 -0
  40. package/effective-kotlin/SKILL.md +225 -0
  41. package/effective-kotlin/assets/example_asset.txt +1 -0
  42. package/effective-kotlin/references/api_reference.md +1 -0
  43. package/effective-kotlin/references/practices-catalog.md +1228 -0
  44. package/effective-kotlin/references/review-checklist.md +126 -0
  45. package/effective-kotlin/scripts/example.py +1 -0
  46. package/kotlin-in-action/SKILL.md +251 -0
  47. package/kotlin-in-action/assets/example_asset.txt +1 -0
  48. package/kotlin-in-action/references/api_reference.md +1 -0
  49. package/kotlin-in-action/references/practices-catalog.md +436 -0
  50. package/kotlin-in-action/references/review-checklist.md +204 -0
  51. package/kotlin-in-action/scripts/example.py +1 -0
  52. package/lean-startup/SKILL.md +250 -0
  53. package/lean-startup/assets/example_asset.txt +1 -0
  54. package/lean-startup/references/api_reference.md +319 -0
  55. package/lean-startup/references/review-checklist.md +137 -0
  56. package/lean-startup/scripts/example.py +1 -0
  57. package/microservices-patterns/SKILL.md +179 -0
  58. package/microservices-patterns/references/patterns-catalog.md +391 -0
  59. package/microservices-patterns/references/review-checklist.md +169 -0
  60. package/package.json +17 -0
  61. package/refactoring-ui/SKILL.md +236 -0
  62. package/refactoring-ui/assets/example_asset.txt +1 -0
  63. package/refactoring-ui/references/api_reference.md +355 -0
  64. package/refactoring-ui/references/review-checklist.md +114 -0
  65. package/refactoring-ui/scripts/example.py +1 -0
  66. package/storytelling-with-data/SKILL.md +238 -0
  67. package/storytelling-with-data/assets/example_asset.txt +1 -0
  68. package/storytelling-with-data/references/api_reference.md +379 -0
  69. package/storytelling-with-data/references/review-checklist.md +111 -0
  70. package/storytelling-with-data/scripts/example.py +1 -0
  71. package/system-design-interview/SKILL.md +213 -0
  72. package/system-design-interview/assets/example_asset.txt +1 -0
  73. package/system-design-interview/references/api_reference.md +582 -0
  74. package/system-design-interview/references/review-checklist.md +201 -0
  75. package/system-design-interview/scripts/example.py +1 -0
  76. package/using-asyncio-python/SKILL.md +242 -0
  77. package/using-asyncio-python/assets/example_asset.txt +1 -0
  78. package/using-asyncio-python/references/api_reference.md +267 -0
  79. package/using-asyncio-python/references/review-checklist.md +149 -0
  80. package/using-asyncio-python/scripts/example.py +1 -0
  81. package/web-scraping-python/SKILL.md +259 -0
  82. package/web-scraping-python/assets/example_asset.txt +1 -0
  83. package/web-scraping-python/references/api_reference.md +393 -0
  84. package/web-scraping-python/references/review-checklist.md +163 -0
  85. package/web-scraping-python/scripts/example.py +1 -0
@@ -0,0 +1,726 @@
1
+ # Design Patterns Catalog
2
+
3
+ Complete reference for all 23 GoF design patterns organized by category, based on
4
+ *Head First Design Patterns* by Eric Freeman & Elisabeth Robson.
5
+
6
+ ---
7
+
8
+ ## Creational Patterns
9
+
10
+ Patterns that deal with object creation mechanisms, trying to create objects in a
11
+ manner suitable to the situation.
12
+
13
+ ### Factory Method
14
+
15
+ **Intent:** Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
16
+
17
+ **Problem it solves:** Client code needs to create objects but shouldn't be coupled to specific concrete classes. New types may be added without modifying existing code.
18
+
19
+ **Participants:**
20
+ - **Creator** — Abstract class with the factory method (e.g., `PizzaStore`)
21
+ - **ConcreteCreator** — Subclass that implements the factory method (e.g., `NYPizzaStore`, `ChicagoPizzaStore`)
22
+ - **Product** — Interface for the objects created (e.g., `Pizza`)
23
+ - **ConcreteProduct** — Specific product classes (e.g., `NYStyleCheesePizza`)
24
+
25
+ **Key characteristics:**
26
+ - Creator declares abstract `factoryMethod()` returning Product type
27
+ - Subclasses override to return specific ConcreteProduct
28
+ - Creator may have default implementation
29
+ - Follows Dependency Inversion Principle: depend on abstractions, not concretions
30
+ - The "decision" of what to create is pushed to subclasses
31
+
32
+ **When to use:**
33
+ - A class can't anticipate the class of objects it must create
34
+ - A class wants its subclasses to specify the objects it creates
35
+ - You need to decouple client code from concrete classes
36
+
37
+ **Book example:** PizzaStore with orderPizza() template and createPizza() factory method. NYPizzaStore and ChicagoPizzaStore decide which pizza style to create.
38
+
39
+ ---
40
+
41
+ ### Abstract Factory
42
+
43
+ **Intent:** Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
44
+
45
+ **Problem it solves:** A system needs to create families of related objects (e.g., all NY-style ingredients or all Chicago-style ingredients) that must be used together.
46
+
47
+ **Participants:**
48
+ - **AbstractFactory** — Interface declaring creation methods for each product type (e.g., `PizzaIngredientFactory`)
49
+ - **ConcreteFactory** — Implements creation for a specific family (e.g., `NYPizzaIngredientFactory`)
50
+ - **AbstractProduct** — Interface for each product type (e.g., `Dough`, `Sauce`, `Cheese`)
51
+ - **ConcreteProduct** — Family-specific products (e.g., `ThinCrustDough`, `MarinaraSauce`)
52
+
53
+ **Key characteristics:**
54
+ - Groups related factory methods into a single interface
55
+ - Ensures compatible products are created together
56
+ - Adding new product families is easy (new ConcreteFactory)
57
+ - Adding new product types requires changing the interface (harder)
58
+ - Often uses Factory Methods internally
59
+
60
+ **When to use:**
61
+ - A system must be independent of how its products are created
62
+ - A system must use one of several families of products
63
+ - Related products are designed to be used together and you need to enforce this constraint
64
+
65
+ **Book example:** PizzaIngredientFactory creates families of ingredients (dough, sauce, cheese, veggies, pepperoni, clams). NYPizzaIngredientFactory and ChicagoPizzaIngredientFactory produce region-specific ingredient sets.
66
+
67
+ ---
68
+
69
+ ### Singleton
70
+
71
+ **Intent:** Ensure a class has only one instance and provide a global point of access to it.
72
+
73
+ **Problem it solves:** Some objects should only have one instance (thread pools, caches, dialog boxes, registry settings, logging objects, device drivers).
74
+
75
+ **Participants:**
76
+ - **Singleton** — Class with a private constructor and a static method that returns the sole instance
77
+
78
+ **Key characteristics:**
79
+ - Private constructor prevents external instantiation
80
+ - Static method (e.g., `getInstance()`) returns the unique instance
81
+ - Lazy initialization: instance created on first request
82
+ - Thread safety considerations are critical:
83
+ - **Eager initialization** — Create at class load time (simplest, always thread-safe)
84
+ - **synchronized method** — Thread-safe but may impact performance
85
+ - **Double-checked locking** — Only synchronize on first creation (use `volatile`)
86
+ - **Enum-based** — Most robust in Java (handles serialization and reflection)
87
+
88
+ **When to use:**
89
+ - Exactly one instance of a class is required
90
+ - The sole instance must be accessible from a well-known access point
91
+ - Be cautious: Singleton is often overused as a glorified global variable
92
+
93
+ **Pitfalls:**
94
+ - Multiple classloaders can create multiple instances
95
+ - Reflection can bypass private constructor
96
+ - Serialization can create new instances (unless handled)
97
+ - Makes unit testing harder due to global state
98
+ - Violates Single Responsibility (manages its own lifecycle + its actual job)
99
+
100
+ **Book example:** Chocolate boiler that must have only one instance to avoid overflow/waste scenarios. Thread-safety issues demonstrated with multiple threads.
101
+
102
+ ---
103
+
104
+ ### Builder
105
+
106
+ **Intent:** Separate the construction of a complex object from its representation so that the same construction process can create different representations.
107
+
108
+ **Problem it solves:** Object creation involves many steps or configurations. Constructors with many parameters become unwieldy. Different representations need the same build process.
109
+
110
+ **Participants:**
111
+ - **Builder** — Interface specifying steps to build each part
112
+ - **ConcreteBuilder** — Implements the steps for a specific representation
113
+ - **Director** — Constructs the object using the Builder interface
114
+ - **Product** — The complex object being built
115
+
116
+ **Key characteristics:**
117
+ - Step-by-step construction process
118
+ - Director controls the algorithm; Builder knows the specifics
119
+ - Same construction process, different resulting products
120
+ - Product is retrieved from the Builder after construction completes
121
+ - Often uses fluent interface (method chaining) in modern implementations
122
+
123
+ **When to use:**
124
+ - Algorithm for creating a complex object should be independent of its parts
125
+ - Construction must allow different representations
126
+ - Constructor has too many parameters (telescoping constructor problem)
127
+
128
+ **Book example:** Vacation planner that builds different types of vacations (outdoor adventure, city sightseeing) using the same step-by-step planning process.
129
+
130
+ ---
131
+
132
+ ### Prototype
133
+
134
+ **Intent:** Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
135
+
136
+ **Problem it solves:** Creating new objects is expensive or complex, but similar objects already exist. You need many instances that differ slightly from existing ones.
137
+
138
+ **Participants:**
139
+ - **Prototype** — Interface declaring a `clone()` method
140
+ - **ConcretePrototype** — Implements clone to copy itself
141
+ - **Client** — Creates new objects by asking a prototype to clone itself
142
+ - **Registry/Manager** — Optional catalog of available prototypes
143
+
144
+ **Key characteristics:**
145
+ - Objects create copies of themselves
146
+ - Shallow vs deep copy considerations are important
147
+ - Avoids expensive creation from scratch
148
+ - Prototype registry allows dynamic addition of new types at runtime
149
+ - Client doesn't need to know concrete classes
150
+
151
+ **When to use:**
152
+ - Creating instances is expensive (database reads, complex computation)
153
+ - System should be independent of how its products are created
154
+ - Classes to instantiate are specified at runtime
155
+ - You need copies of existing objects with slight modifications
156
+
157
+ **Book example:** Monster registry where game creates new monsters by cloning prototypical instances rather than constructing from scratch each time.
158
+
159
+ ---
160
+
161
+ ## Structural Patterns
162
+
163
+ Patterns that deal with object composition, creating relationships between objects
164
+ to form larger structures.
165
+
166
+ ### Adapter
167
+
168
+ **Intent:** Convert the interface of a class into another interface that clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
169
+
170
+ **Problem it solves:** You have an existing class whose interface doesn't match what client code needs. You want to use a third-party class but its interface doesn't fit your system.
171
+
172
+ **Participants:**
173
+ - **Target** — The interface the client expects (e.g., `Duck`)
174
+ - **Adapter** — Translates calls from Target interface to Adaptee (e.g., `TurkeyAdapter`)
175
+ - **Adaptee** — The existing class with an incompatible interface (e.g., `Turkey`)
176
+ - **Client** — Works with the Target interface
177
+
178
+ **Key characteristics:**
179
+ - Object Adapter uses composition (wraps adaptee) — preferred
180
+ - Class Adapter uses multiple inheritance (where available)
181
+ - Adapter translates method calls, may need to handle mismatches in methods
182
+ - Can adapt a single class or multiple classes (facade-like adapter)
183
+ - The adaptee doesn't know it's being adapted
184
+
185
+ **When to use:**
186
+ - You want to use an existing class but its interface doesn't match your needs
187
+ - You want to create a reusable class that cooperates with unrelated classes
188
+ - You need to use several existing subclasses but can't adapt each by subclassing
189
+
190
+ **Book example:** TurkeyAdapter wrapping Turkey to make it work where Duck is expected. Also Enumeration-to-Iterator adapter for Java legacy collections.
191
+
192
+ ---
193
+
194
+ ### Bridge
195
+
196
+ **Intent:** Decouple an abstraction from its implementation so that the two can vary independently.
197
+
198
+ **Problem it solves:** You have a class hierarchy that is growing in two dimensions (e.g., different types AND different platforms). Without Bridge, you get a combinatorial explosion of subclasses.
199
+
200
+ **Participants:**
201
+ - **Abstraction** — High-level control interface (e.g., `RemoteControl`)
202
+ - **RefinedAbstraction** — Extension of the abstraction (e.g., `AdvancedRemoteControl`)
203
+ - **Implementor** — Interface for implementation classes (e.g., `TV`)
204
+ - **ConcreteImplementor** — Specific implementation (e.g., `SonyTV`, `LGTV`)
205
+
206
+ **Key characteristics:**
207
+ - Abstraction holds a reference to an Implementor
208
+ - Both hierarchies can be extended independently
209
+ - Avoids permanent binding between abstraction and implementation
210
+ - Composition replaces inheritance across two dimensions
211
+ - Changes to implementation don't affect client code
212
+
213
+ **When to use:**
214
+ - You want to avoid a permanent binding between abstraction and implementation
215
+ - Both abstractions and implementations should be extensible by subclassing
216
+ - Implementation changes should not impact clients
217
+ - You have a proliferation of classes resulting from coupled interface/implementation hierarchy
218
+
219
+ **Book example:** Remote controls (abstraction) and TVs (implementation). New remote features and new TV brands can be added independently without affecting each other.
220
+
221
+ ---
222
+
223
+ ### Composite
224
+
225
+ **Intent:** Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
226
+
227
+ **Problem it solves:** You need to represent hierarchical structures where both individual items and groups of items should be treated the same way (menus with sub-menus, file systems, organizational charts).
228
+
229
+ **Participants:**
230
+ - **Component** — Interface for all objects in the composition (e.g., `MenuComponent`)
231
+ - **Leaf** — Represents end objects with no children (e.g., `MenuItem`)
232
+ - **Composite** — Has children, implements child-related operations (e.g., `Menu`)
233
+ - **Client** — Manipulates objects through the Component interface
234
+
235
+ **Key characteristics:**
236
+ - Tree structure with uniform interface
237
+ - Leaves and composites implement the same interface
238
+ - Composites delegate to children and may add own behavior
239
+ - Trade-off: transparency (uniform interface) vs safety (separate leaf/composite types)
240
+ - Null Iterator pattern for leaves that have no children
241
+ - Component may throw UnsupportedOperationException for inapplicable methods
242
+
243
+ **When to use:**
244
+ - You want to represent part-whole hierarchies of objects
245
+ - You want clients to ignore the difference between compositions and individual objects
246
+ - All objects in the structure should be treated uniformly
247
+
248
+ **Book example:** Restaurant menu system with Menus containing MenuItems and sub-Menus. Printing the entire menu hierarchy traverses the composite tree uniformly.
249
+
250
+ ---
251
+
252
+ ### Decorator
253
+
254
+ **Intent:** Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
255
+
256
+ **Problem it solves:** You need to add behavior to individual objects without affecting others of the same class. Subclassing for every combination leads to class explosion.
257
+
258
+ **Participants:**
259
+ - **Component** — Interface for objects that can have responsibilities added (e.g., `Beverage`)
260
+ - **ConcreteComponent** — Object to which additional responsibilities can be attached (e.g., `DarkRoast`)
261
+ - **Decorator** — Abstract class that wraps a Component and conforms to its interface (e.g., `CondimentDecorator`)
262
+ - **ConcreteDecorator** — Adds responsibilities (e.g., `Mocha`, `Whip`, `Soy`)
263
+
264
+ **Key characteristics:**
265
+ - Decorators have the same supertype as the objects they decorate
266
+ - One or more decorators can wrap an object
267
+ - Decorator adds its own behavior before/after delegating to the wrapped object
268
+ - Objects can be decorated at runtime with any combination
269
+ - Follows Open-Closed Principle: extend behavior without modifying existing code
270
+ - Can result in many small objects — harder to debug
271
+
272
+ **When to use:**
273
+ - You need to add responsibilities to individual objects dynamically and transparently
274
+ - Extending functionality by subclassing is impractical (too many combinations)
275
+ - You want to add behavior that can be withdrawn later
276
+
277
+ **Book example:** Starbuzz Coffee with beverages and condiments. Mocha(Whip(DarkRoast)) computes cost and description by wrapping, each decorator adding its price and label.
278
+
279
+ ---
280
+
281
+ ### Facade
282
+
283
+ **Intent:** Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
284
+
285
+ **Problem it solves:** A subsystem has many classes with complex interactions. Clients need a simpler way to perform common tasks without understanding the subsystem's internals.
286
+
287
+ **Participants:**
288
+ - **Facade** — Provides simplified methods that delegate to subsystem classes (e.g., `HomeTheaterFacade`)
289
+ - **Subsystem classes** — The complex classes being simplified (e.g., `Amplifier`, `DVDPlayer`, `Projector`, `Screen`, `PopcornPopper`)
290
+
291
+ **Key characteristics:**
292
+ - Doesn't encapsulate subsystem — clients can still use subsystem directly if needed
293
+ - Simplifies the interface without adding new functionality
294
+ - Decouples client from subsystem classes
295
+ - Follows Principle of Least Knowledge (Law of Demeter)
296
+ - Can have multiple facades for different aspects of a subsystem
297
+ - Facade doesn't prevent direct access to subsystem when needed
298
+
299
+ **When to use:**
300
+ - You want to provide a simple interface to a complex subsystem
301
+ - There are many dependencies between clients and implementation classes
302
+ - You want to layer your subsystems
303
+
304
+ **Book example:** Home theater system where watchMovie() coordinates turning on amplifier, setting tuner, dimming lights, lowering screen, starting projector, and playing the DVD.
305
+
306
+ ---
307
+
308
+ ### Flyweight
309
+
310
+ **Intent:** Use sharing to support large numbers of fine-grained objects efficiently.
311
+
312
+ **Problem it solves:** An application needs a huge number of objects that share common state. Storing all state in each object would consume too much memory.
313
+
314
+ **Participants:**
315
+ - **Flyweight** — Interface through which flyweights receive and act on extrinsic state
316
+ - **ConcreteFlyweight** — Stores intrinsic (shared) state
317
+ - **FlyweightFactory** — Creates and manages flyweight objects, ensures proper sharing
318
+ - **Client** — Maintains extrinsic state, passes it to flyweights
319
+
320
+ **Key characteristics:**
321
+ - **Intrinsic state** — Stored in the flyweight, shared, context-independent (e.g., tree type, texture)
322
+ - **Extrinsic state** — Stored externally, context-dependent, passed to flyweight (e.g., position, age)
323
+ - Factory ensures flyweights are shared (returns existing instance or creates new)
324
+ - Dramatic reduction in number of objects
325
+ - Trade-off: computation time for looking up/computing extrinsic state
326
+
327
+ **When to use:**
328
+ - An application uses a large number of objects
329
+ - Storage costs are high due to sheer quantity
330
+ - Most object state can be made extrinsic
331
+ - Many groups of objects can be replaced by relatively few shared objects
332
+ - The application doesn't depend on object identity
333
+
334
+ **Book example:** Tree landscape with thousands of trees. Each tree type (oak, birch, pine) is a flyweight with shared texture/shape. Position (x, y) is extrinsic state.
335
+
336
+ ---
337
+
338
+ ### Proxy
339
+
340
+ **Intent:** Provide a surrogate or placeholder for another object to control access to it.
341
+
342
+ **Problem it solves:** You need to control access to an object — for remote access, lazy loading, access control, logging, caching, or other cross-cutting concerns.
343
+
344
+ **Participants:**
345
+ - **Subject** — Interface shared by RealSubject and Proxy
346
+ - **RealSubject** — The actual object being proxied
347
+ - **Proxy** — Controls access to RealSubject, may create/manage it
348
+
349
+ **Proxy variants:**
350
+ - **Remote Proxy** — Represents an object in a different JVM/address space (e.g., Java RMI). The proxy handles network communication transparently
351
+ - **Virtual Proxy** — Creates expensive objects on demand. Displays a placeholder until the real object is loaded (e.g., image loading with placeholder)
352
+ - **Protection Proxy** — Controls access based on permissions (e.g., Java's dynamic Proxy with InvocationHandler checks caller rights)
353
+ - **Other variants** — Firewall proxy, caching proxy, synchronization proxy, smart reference proxy, copy-on-write proxy
354
+
355
+ **Key characteristics:**
356
+ - Proxy and RealSubject share the same interface
357
+ - Proxy holds a reference to RealSubject (or can create it)
358
+ - Proxy adds control logic before/after delegating to RealSubject
359
+ - Similar structure to Decorator, but different intent: Proxy controls access, Decorator adds behavior
360
+ - Java dynamic proxy creates proxy classes at runtime
361
+
362
+ **When to use:**
363
+ - You need a local representative for a remote object
364
+ - You want to create expensive objects only on demand
365
+ - You need to control access to the original object
366
+ - You want a smart reference (reference counting, locking, etc.)
367
+
368
+ **Book example:** Gumball machine monitoring via Remote Proxy (Java RMI). Virtual Proxy for CD cover images loading asynchronously. Protection Proxy using Java's InvocationHandler to control who can set ratings.
369
+
370
+ ---
371
+
372
+ ## Behavioral Patterns
373
+
374
+ Patterns that deal with communication between objects, how objects interact and
375
+ distribute responsibility.
376
+
377
+ ### Strategy
378
+
379
+ **Intent:** Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
380
+
381
+ **Problem it solves:** Multiple related classes differ only in their behavior. You need different variants of an algorithm. Conditional statements for selecting desired behavior become complex.
382
+
383
+ **Participants:**
384
+ - **Strategy** — Interface common to all supported algorithms (e.g., `FlyBehavior`)
385
+ - **ConcreteStrategy** — Implements the algorithm (e.g., `FlyWithWings`, `FlyNoWay`)
386
+ - **Context** — Configured with a Strategy, delegates to it (e.g., `Duck`)
387
+
388
+ **Key characteristics:**
389
+ - Context composes a Strategy via an interface field
390
+ - Behavior can be changed at runtime via setter
391
+ - Eliminates conditional statements for selecting behavior
392
+ - Follows "encapsulate what varies" and "program to interfaces"
393
+ - Favors composition over inheritance
394
+ - Each strategy is independently testable
395
+
396
+ **When to use:**
397
+ - Many related classes differ only in behavior
398
+ - You need different variants of an algorithm
399
+ - An algorithm uses data that clients shouldn't know about
400
+ - A class defines many behaviors via conditional statements
401
+
402
+ **Book example:** SimUDuck where ducks compose FlyBehavior and QuackBehavior. MallardDuck flies with wings, RubberDuck squeaks, and behaviors can be swapped at runtime with setFlyBehavior().
403
+
404
+ ---
405
+
406
+ ### Observer
407
+
408
+ **Intent:** Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
409
+
410
+ **Problem it solves:** Multiple objects need to stay synchronized with another object's state. Tight coupling between the source of data and its consumers makes the system rigid.
411
+
412
+ **Participants:**
413
+ - **Subject** — Maintains list of observers, sends notifications (e.g., `WeatherData`)
414
+ - **Observer** — Interface for objects that should be notified (e.g., `Observer` with `update()`)
415
+ - **ConcreteSubject** — Stores state of interest, notifies observers when state changes
416
+ - **ConcreteObserver** — Maintains reference to ConcreteSubject, implements update (e.g., `CurrentConditionsDisplay`)
417
+
418
+ **Key characteristics:**
419
+ - Loose coupling: Subject knows only the Observer interface
420
+ - Observers can be added/removed at runtime
421
+ - **Push model** — Subject sends data with notification
422
+ - **Pull model** — Observer queries Subject for data after notification
423
+ - Subject doesn't need to know concrete observer classes
424
+ - Be careful with notification order dependencies
425
+ - Remember to unregister observers to prevent memory leaks
426
+
427
+ **When to use:**
428
+ - When a change to one object requires changing others, and you don't know how many
429
+ - When an object should notify others without making assumptions about who they are
430
+ - When you need a publish-subscribe mechanism
431
+
432
+ **Book example:** WeatherStation where WeatherData (Subject) notifies CurrentConditionsDisplay, StatisticsDisplay, and ForecastDisplay (Observers) whenever measurements change.
433
+
434
+ ---
435
+
436
+ ### Command
437
+
438
+ **Intent:** Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
439
+
440
+ **Problem it solves:** You need to issue requests to objects without knowing anything about the operation being requested or the receiver. You need to support undo/redo, queuing, logging.
441
+
442
+ **Participants:**
443
+ - **Command** — Interface declaring `execute()` (and optionally `undo()`)
444
+ - **ConcreteCommand** — Binds a receiver to an action (e.g., `LightOnCommand`)
445
+ - **Invoker** — Asks the command to carry out the request (e.g., `RemoteControl`)
446
+ - **Receiver** — Knows how to perform the actual work (e.g., `Light`, `Stereo`)
447
+ - **Client** — Creates commands and sets their receivers
448
+
449
+ **Key characteristics:**
450
+ - Decouples invoker from receiver
451
+ - Commands can be stored, queued, and logged
452
+ - **Undo** — Command stores previous state; `undo()` reverses `execute()`
453
+ - **Macro Command** — Command that executes a sequence of commands
454
+ - **NoCommand** (Null Object) — Placeholder command that does nothing; eliminates null checks
455
+ - Commands can be serialized for replay or remote execution
456
+
457
+ **When to use:**
458
+ - Parameterize objects with an action to perform
459
+ - Specify, queue, and execute requests at different times
460
+ - Support undo/redo functionality
461
+ - Support logging changes so they can be reapplied after a crash
462
+ - Structure a system around high-level operations built from primitives
463
+
464
+ **Book example:** Universal remote control where buttons are assigned commands. LightOnCommand, StereoOnWithCDCommand, etc. Undo button reverses last command. Party mode via MacroCommand.
465
+
466
+ ---
467
+
468
+ ### Template Method
469
+
470
+ **Intent:** Define the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps without changing the algorithm's structure.
471
+
472
+ **Problem it solves:** Two or more classes have algorithms with the same structure but different steps. Duplicating the algorithm in each class violates DRY.
473
+
474
+ **Participants:**
475
+ - **AbstractClass** — Defines the template method and abstract primitive operations (e.g., `CaffeineBeverage`)
476
+ - **ConcreteClass** — Implements the primitive operations (e.g., `Tea`, `Coffee`)
477
+
478
+ **Key characteristics:**
479
+ - Template method defines the algorithm structure, calls abstract/hook methods
480
+ - **Abstract methods** — Subclasses MUST implement these steps
481
+ - **Hook methods** — Subclasses CAN override these; default (often empty) implementation provided
482
+ - **Hollywood Principle** — "Don't call us, we'll call you." Superclass controls when subclasses are called
483
+ - Template method itself should be `final` to prevent subclass overriding
484
+ - Strategy vs Template Method: Strategy uses composition, Template Method uses inheritance
485
+
486
+ **When to use:**
487
+ - Implement the invariant parts of an algorithm once and leave variable parts to subclasses
488
+ - Common behavior among subclasses should be factored into a common class to avoid duplication
489
+ - Control subclass extensions (hooks let subclasses extend at specific points)
490
+
491
+ **Book example:** CaffeineBeverage prepareRecipe() calls boilWater(), brew(), pourInCup(), addCondiments(). Tea and Coffee implement brew() and addCondiments() differently. Hook: customerWantsCondiments().
492
+
493
+ ---
494
+
495
+ ### Iterator
496
+
497
+ **Intent:** Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
498
+
499
+ **Problem it solves:** Collections have different internal structures (arrays, lists, hashtables) but clients need a uniform way to traverse them without knowing the internals.
500
+
501
+ **Participants:**
502
+ - **Iterator** — Interface for accessing and traversing elements (`hasNext()`, `next()`)
503
+ - **ConcreteIterator** — Implements Iterator for a specific aggregate
504
+ - **Aggregate** — Interface for creating an Iterator (`createIterator()`)
505
+ - **ConcreteAggregate** — Implements the Aggregate; returns appropriate ConcreteIterator
506
+
507
+ **Key characteristics:**
508
+ - Uniform traversal interface regardless of collection type
509
+ - Collection doesn't expose its internal structure
510
+ - Multiple iterators can traverse the same collection simultaneously
511
+ - Follows Single Responsibility Principle: collection manages elements, iterator manages traversal
512
+ - In Java, `java.util.Iterator` provides standard interface
513
+ - Internal vs external iterators (who controls traversal)
514
+
515
+ **When to use:**
516
+ - Access a collection's contents without exposing its internal representation
517
+ - Support multiple traversals of collections
518
+ - Provide a uniform interface for traversing different collection structures
519
+
520
+ **Book example:** Diner menu (array) and Pancake House menu (ArrayList) need a common way for a waitress to iterate. Each menu provides an Iterator, waitress uses the same loop for both.
521
+
522
+ ---
523
+
524
+ ### State
525
+
526
+ **Intent:** Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
527
+
528
+ **Problem it solves:** An object's behavior depends on its state, and it must change behavior at runtime depending on that state. Large conditional statements test the current state and select behavior.
529
+
530
+ **Participants:**
531
+ - **State** — Interface defining behavior for each state (e.g., `State` with insertQuarter(), turnCrank(), etc.)
532
+ - **ConcreteState** — Each state implements behavior appropriate for that state (e.g., `HasQuarterState`, `SoldState`)
533
+ - **Context** — Maintains a current State instance, delegates behavior to it (e.g., `GumballMachine`)
534
+
535
+ **Key characteristics:**
536
+ - Eliminates large conditional blocks (switch/if-else on state)
537
+ - State transitions handled by state objects (or by context — design choice)
538
+ - Each state encapsulates its own behavior
539
+ - Similar class diagram to Strategy, but different intent:
540
+ - Strategy: client chooses algorithm, typically configured once
541
+ - State: transitions happen automatically based on context, behavior changes over time
542
+ - New states can be added without modifying existing state classes (Open-Closed Principle)
543
+ - Context delegates to current state for all state-dependent behavior
544
+
545
+ **When to use:**
546
+ - Object behavior depends on its state and changes at runtime
547
+ - Operations have large multipart conditional statements depending on state
548
+ - You want to make state transitions explicit
549
+
550
+ **Book example:** Gumball machine with NoQuarterState, HasQuarterState, SoldState, SoldOutState. Each state handles all actions (insert quarter, eject, turn crank, dispense) appropriately for its context.
551
+
552
+ ---
553
+
554
+ ### Chain of Responsibility
555
+
556
+ **Intent:** Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
557
+
558
+ **Problem it solves:** Multiple objects may handle a request, and the handler isn't known a priori. The set of handlers and their order should be configurable.
559
+
560
+ **Participants:**
561
+ - **Handler** — Interface defining handleRequest(); may include successor reference
562
+ - **ConcreteHandler** — Handles requests it's responsible for; forwards others to successor
563
+ - **Client** — Initiates the request to a handler in the chain
564
+
565
+ **Key characteristics:**
566
+ - Request travels along the chain until handled (or falls off the end)
567
+ - Sender doesn't know which handler will process the request
568
+ - Chain can be configured dynamically
569
+ - Each handler decides: handle or pass along
570
+ - No guarantee the request will be handled (may need a default handler)
571
+ - Reduces coupling between sender and receiver
572
+
573
+ **When to use:**
574
+ - More than one object may handle a request and the handler is not known a priori
575
+ - You want to issue a request to one of several objects without specifying the receiver explicitly
576
+ - The set of handlers should be specified dynamically
577
+
578
+ **Book example:** Email handler chain: SpamHandler → FanHandler → ComplaintHandler → NewLocationHandler. Each handler checks if it should process the email, otherwise passes it to the next handler.
579
+
580
+ ---
581
+
582
+ ### Interpreter
583
+
584
+ **Intent:** Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
585
+
586
+ **Problem it solves:** You have a simple language or grammar that needs to be interpreted. Each rule in the grammar can be represented as a class.
587
+
588
+ **Participants:**
589
+ - **AbstractExpression** — Interface for interpret() operation
590
+ - **TerminalExpression** — Implements interpret for terminal symbols in the grammar
591
+ - **NonterminalExpression** — Implements interpret for grammar rules (contains other expressions)
592
+ - **Context** — Contains global information for the interpreter
593
+ - **Client** — Builds the abstract syntax tree and invokes interpret
594
+
595
+ **Key characteristics:**
596
+ - Each grammar rule becomes a class
597
+ - Abstract syntax tree (AST) represents sentences in the language
598
+ - Easy to change/extend the grammar by adding new expression classes
599
+ - Complex grammars become hard to maintain (use parser generators for those)
600
+ - Works best for simple, well-defined languages
601
+
602
+ **When to use:**
603
+ - The grammar is simple (complex grammars need parser generators)
604
+ - Efficiency is not a critical concern
605
+ - You need an easy way to interpret/evaluate a language
606
+
607
+ **Book example:** Musical notation interpreter where expressions represent notes, rests, and sequences. Each grammar rule is a class with an interpret method.
608
+
609
+ ---
610
+
611
+ ### Mediator
612
+
613
+ **Intent:** Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly.
614
+
615
+ **Problem it solves:** Many objects communicate with many others in complex ways. Direct references create a tangled web of dependencies that's hard to understand and modify.
616
+
617
+ **Participants:**
618
+ - **Mediator** — Interface defining communication between colleague objects
619
+ - **ConcreteMediator** — Coordinates communication between colleagues; knows all colleagues
620
+ - **Colleague** — Each object communicates through the mediator rather than directly with others
621
+
622
+ **Key characteristics:**
623
+ - Centralizes complex communication and control logic
624
+ - Colleagues only know the mediator, not each other
625
+ - Simplifies object protocols (many-to-many → many-to-one)
626
+ - Mediator can become a God Object if not careful
627
+ - Promotes loose coupling between colleagues
628
+ - Trade-off: complexity moves from distributed interactions to centralized mediator
629
+
630
+ **When to use:**
631
+ - A set of objects communicate in well-defined but complex ways
632
+ - Reusing an object is difficult because it refers to many other objects
633
+ - Behavior distributed between several classes should be customizable without subclassing
634
+
635
+ **Book example:** Home automation where an alarm clock, calendar, coffee maker, and sprinkler system communicate through a mediator. Calendar event triggers alarm, which triggers coffee maker, all coordinated by the mediator.
636
+
637
+ ---
638
+
639
+ ### Memento
640
+
641
+ **Intent:** Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.
642
+
643
+ **Problem it solves:** You need to implement undo, checkpoint, or rollback functionality. Saving/restoring state directly would expose internal details and violate encapsulation.
644
+
645
+ **Participants:**
646
+ - **Originator** — Object whose state needs to be saved; creates and restores from Memento
647
+ - **Memento** — Stores the internal state of the Originator; opaque to other objects
648
+ - **Caretaker** — Responsible for keeping the Memento; never examines or modifies its contents
649
+
650
+ **Key characteristics:**
651
+ - Preserves encapsulation: only Originator can access Memento's internals
652
+ - Caretaker holds mementos but doesn't know their contents
653
+ - Can store multiple mementos for multi-level undo
654
+ - May be expensive if Originator state is large
655
+ - Consider incremental changes vs full snapshots
656
+ - Originator creates memento, Caretaker stores it, Originator restores from it
657
+
658
+ **When to use:**
659
+ - A snapshot of an object's state must be saved for later restoration
660
+ - A direct interface to obtaining the state would expose implementation details
661
+ - You need to implement undo/redo, checkpoints, or transactions
662
+
663
+ **Book example:** Save game state where the game (Originator) creates a Memento of its state, the system (Caretaker) stores it, and the game can restore to any saved state later.
664
+
665
+ ---
666
+
667
+ ### Visitor
668
+
669
+ **Intent:** Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
670
+
671
+ **Problem it solves:** You have a stable class hierarchy but need to add new operations frequently. Adding methods to each class for every new operation pollutes the interface and requires changing all classes.
672
+
673
+ **Participants:**
674
+ - **Visitor** — Interface declaring visit method for each element type
675
+ - **ConcreteVisitor** — Implements operations for each element type (e.g., `NutritionVisitor`, `PricingVisitor`)
676
+ - **Element** — Interface declaring accept(Visitor) method
677
+ - **ConcreteElement** — Implements accept by calling visitor.visit(this) (double dispatch)
678
+ - **ObjectStructure** — Collection of elements that can be iterated
679
+
680
+ **Key characteristics:**
681
+ - **Double dispatch** — Operation depends on both Visitor type AND Element type
682
+ - Element.accept(visitor) → visitor.visit(element): two method calls determine behavior
683
+ - Easy to add new operations (new Visitor class) without changing elements
684
+ - Hard to add new element types (must update all Visitors)
685
+ - Gathers related operations in a Visitor instead of spreading across element classes
686
+ - Elements must expose enough state for Visitors to work
687
+
688
+ **When to use:**
689
+ - An object structure contains many classes with differing interfaces and you want to perform operations that depend on concrete classes
690
+ - Many distinct/unrelated operations need to be performed on objects in a structure
691
+ - The classes defining the structure rarely change, but you often want to define new operations
692
+
693
+ **Book example:** Menu items with NutritionVisitor and PricingVisitor. Each visitor traverses menu items, computing nutritional info or prices without modifying the MenuItem classes.
694
+
695
+ ---
696
+
697
+ ## Compound Patterns
698
+
699
+ ### MVC (Model-View-Controller)
700
+
701
+ **Intent:** Separate an application into three interconnected components to separate internal representations from the ways information is presented and accepted by the user.
702
+
703
+ **Patterns used:**
704
+ - **Observer** — Model notifies Views when state changes
705
+ - **Strategy** — View uses Controller as its strategy for handling user input
706
+ - **Composite** — View hierarchy is a composite structure (panels contain buttons, labels, etc.)
707
+
708
+ **Participants:**
709
+ - **Model** — Application data and business logic; notifies observers (views) of changes
710
+ - **View** — Renders the model's data; observes model for updates; delegates user actions to controller
711
+ - **Controller** — Takes user input from view, interprets it, and manipulates the model; acts as the strategy for the view
712
+
713
+ **Key characteristics:**
714
+ - Model is completely independent of View and Controller
715
+ - Views can be swapped without changing the Model
716
+ - Controllers can be swapped to change input handling behavior
717
+ - Multiple Views can observe the same Model simultaneously
718
+ - **Model 2 (Web MVC)** — Adapted for web: Controller is a servlet, View is a JSP/template, Model is a POJO/bean
719
+ - Clean separation of concerns enables independent testing and development
720
+
721
+ **When to use:**
722
+ - Building interactive applications where presentation and data should be decoupled
723
+ - Multiple views of the same data are needed
724
+ - User interface needs to be easily changeable or replaceable
725
+
726
+ **Book example:** DJ beat controller where BeatModel (Model) tracks BPM and notifies DJView (View) of changes. BeatController (Controller) handles user interactions like setting BPM and starting/stopping beats.