Strategy
The Strategy Design Pattern¶
Classification¶
- Behavioral Design Pattern
Pattern Definition¶
- Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
- In the strategy pattern, the interchangeable algorithms are called Strategies and the object that holds one and delegates to it is called the Context.
Representations¶
Mermaid Graph¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
UML¶
Usage¶
- Useful when several objects differ only in their behavior, or when one object needs to change its behavior while it is running.
Real World Usages¶
- Java Collections use Strategy: a Comparator is handed to
sort()so the ordering algorithm varies independently of the collection being sorted. - Swing and AWT Layout Managers use Strategy: a Container HAS-A LayoutManager, and
setLayout()swaps the arrangement algorithm at runtime. - Java Cryptography (JCE) uses Strategy:
Cipher.getInstance("AES/CBC/PKCS5Padding")selects an algorithm by name at runtime behind one interface. - Thread pools use Strategy: a ThreadPoolExecutor takes a RejectedExecutionHandler that decides what happens when the work queue is full.
- Spring uses Strategy throughout: PlatformTransactionManager, ResourceLoader, and the various
*Resolverinterfaces are all swappable algorithms behind a common type. - Lambdas and method references are Strategy with less ceremony: any functional interface parameter is an algorithm being passed in.
Application to my Real World Application¶
- Application: ETL Pipeline
- Pattern Application: Vary the algorithm a Stage runs without changing the Stage itself
- Breakdown: Context is a Stage that HAS-A Strategy and delegates its real work to it. An Extract stage holds a ParseStrategy (CSV, JSON, fixed-width) so a new feed format is a new class rather than an edit; a Transform stage holds a TransformStrategy (Deduplicate, NormalizeDates, RedactPII); a Load stage holds a WriteStrategy (BulkInsert, Upsert, Append). Because the strategy is chosen from configuration at startup, one Pipeline binary serves many feeds, and because it is a field rather than a subclass, a stage can swap algorithms mid-run — for example dropping from BulkInsert to Upsert after the first duplicate-key failure.
Java Code Example¶
Main Take-Aways from the textbook¶
- The Strategy Pattern defines a family of algorithms and makes them interchangeable.
- Behaviors live in their own set of classes instead of inside the class hierarchy that uses them.
- A Context HAS-A behavior rather than IS-A behavior; it delegates to the behavior instead of inheriting it.
- Because the behavior is a field, it can be replaced while the program is running. Inheritance cannot do this — an object’s class is fixed the moment it is constructed.
- Using inheritance to reuse behavior leads to a class explosion: N types multiplied by M behaviors. Composition turns that multiplication into an addition.
- The Context is written against the Strategy interface, so a new algorithm is a new class and nothing that already works has to change.
- Strategy and State have almost the same class diagram and opposite intent: with Strategy the client chooses the algorithm and the algorithms never reference each other, while with State the object chooses its own next state and the states do reference each other.
- Patterns give you a shared vocabulary. Saying “that field is a Strategy” tells another developer the structure, the intent, and the trade-off in three words.
Main OO Principles of Strategy Pattern¶
- Encapsulate what Varies
- The algorithm is the thing that varies, so it is pulled out of the Context and into its own set of classes. What stays the same — when the algorithm runs, and what happens with the result — stays in the Context.
- Program to an Interface not an Implementation
- The Context holds a reference of the Strategy interface type and never names a concrete strategy. Adding an algorithm requires no change to the Context.
- Favor composition over inheritance
- The Context maintains a Strategy reference, which is composition. This is what makes the behavior swappable at runtime, and it is the whole reason the pattern beats a subclass hierarchy.
- Strive for loosely coupled designs
- The Context knows only that its Strategy has an
execute()method, and the concrete strategies know nothing about each other at all. Either side can be replaced without the other noticing.
- The Context knows only that its Strategy has an