Strategy pattern Flashcards
Learn Strategy pattern here! (60 cards)
Q: What key concepts are introduced on Page 1 of the Strategy Pattern chapter?
A:
Purpose of Design Patterns:
Reuse solutions from experienced developers who solved similar problems
“Load your brain” with patterns to recognize where to apply them
Focus on experience reuse rather than just code reuse
Core Idea:
Someone has already solved your design problems
Exploit collective wisdom through patterns
Chapter Preview:
Covers pattern benefits
Key OO design principles
Walkthrough of a pattern example
Tone Setting:
Playful analogy: “Objectville” and “Jim and Betty’s patterns group”
Emphasizes practical, community-vetted solutions
Bonus Mnemonic:
“REP your brain” → Recognize patterns, Experience reuse, Practical solutions.
Flashcard 1 (Initial Design)
Q: What was the original OO design of the SimUDuck app?
A:
Duck superclass with inherited methods:
quack() and swim() (concrete implementations)
display() (abstract, forced implementation by subclasses)
Subclasses:
MallardDuck, RedheadDuck, etc. (override display())
Key Limitation:
❌ All ducks inherit fly(), even inappropriate ones (e.g., RubberDuck).
Flashcard 2 (Problem Trigger)
Q: What change triggered the design problem?
A:
New requirement: Ducks must fly to compete with rivals.
Flawed solution: Added fly() to Duck superclass → Rubber ducks flew unintentionally.
Side Effect:
🔥 “Localized update caused non-local side effects” (flying rubber ducks).
Flashcard 3 (Inheritance Issues)
Q: Why was overriding fly() in subclasses a bad solution?
A:
Duplication: Override fly() to do nothing in RubberDuck, DecoyDuck, etc.
Maintenance hell: Future ducks require repetitive overrides.
No reuse: Each subclass manages behavior independently.
Example:
class RubberDuck {
fly() { /* do nothing */ } // Redundant!
}
Flashcard 4 (Failed Interface Attempt)
Q: How did interfaces (Flyable, Quackable) fail to solve the problem?
A:
Pros: Only flying ducks implement Flyable.
Cons:
No code reuse: Each class reimplements behavior.
Runtime changes impossible: Behaviors hardcoded per class.
Diagram:
Duck → (no fly/quack)
↑
MallardDuck → implements Flyable, Quackable
RubberDuck → implements Quackable
Flashcard 5 (Key Insight)
Q: What was the critical realization about the design flaw?
A:
Root cause: Inheritance mixes what varies (fly/quack) with what stays the same (swim/display).
Solution needed: Separate behaviors that change (fly/quack) from stable ones.
Principle Preview:
🔧 “Encapsulate what varies.”
Visual Summary
Visual Summary
Original Design:
Copy
Duck
/ | \
Mallard Rubber Decoy
Problem: All ducks forced to inherit fly/quack.
Interface Attempt:
Copy
Duck
/ | \
Mallard (Flyable) Rubber (Quackable)
Problem: Duplicated code, no flexibility.
Flashcard 1 (Inheritance Override Pitfall)
Q: Why was overriding fly()/quack() in subclasses like RubberDuck a poor solution?
A:
Duplication: Every non-flying duck (e.g., RubberDuck, DecoyDuck) must override fly() to do nothing.
Brittle: Adding new ducks forces repetitive overrides.
Violates DRY: Same “do nothing” code appears in multiple classes.
Code Example:
class RubberDuck {
fly() { /* Empty override / }
quack() { / Squeak */ }
}
Flashcard 2 (Inheritance Disadvantages)
Q: What are the 6 key disadvantages of using inheritance for duck behaviors? (Page 5 “Sharpen Your Pencil”)
A:
Code duplication across subclasses (A)
Runtime behavior changes are difficult (B)
Hard to track all duck behaviors (D)
Changes unintentionally affect other ducks (F)
(C and E are red herrings – dancing and simultaneous actions aren’t relevant)
Key Quote:
“What he thought was a great use of inheritance for reuse turned out poorly for maintenance.”
Flashcard 3 (Interface Attempt)
Q: How did the Flyable/Quackable interface approach fail? (Page 6)
Pros: Only flying ducks implement Flyable.
Cons:
No code reuse: Each class rewrites fly()/quack().
Maintenance nightmare: Changing behavior requires updating all implementers.
No runtime flexibility: Behaviors locked at compile time.
Visual:
Duck → (no fly/quack)
↑
MallardDuck → implements Flyable (writes fly() from scratch)
Flashcard 4 (Critical Insight)
Q: What fundamental problem did both failed approaches share? (Page 7)
A:
Both tightly coupled behaviors to the Duck class hierarchy:
Inheritance: Behaviors baked into superclass/subclasses.
Interfaces: Behaviors scattered across implementers.
Solution Needed: Decouple behaviors entirely.
Design Principle Teaser:
🔧 “Program to an interface, not an implementation.”
Flashcard 5 (Why Interfaces Fell Short)
Q: Why didn’t interfaces solve the code reuse problem? (Page 6-7)
A:
Java interfaces lack implementation code:
Every Flyable duck rewrites fly().
No shared default behavior (e.g., FlyWithWings).
Example:
MallardDuck and RedheadDuck both write identical fly() code.
Key Quote:
“It completely destroys code reuse […] creating a different maintenance nightmare.”
Flashcard 6 (Transition to Strategy)
Q: What hint does the text give about the upcoming solution? (Page 7 bottom)
A:
Clue: “We’re going to figure out a solution by applying good OO design principles.”
Principles Foreshadowed:
Encapsulate what varies.
Program to interfaces.
Favor composition.
Analogy:
“Wouldn’t it be dreamy if […] we could change [code] with the least possible impact?”
Summary Table: Failed Solutions
Approach Pros
Cons
Inheritance Reuse via inheritance
Inflexible, duplicates
code
Interfaces Selective behavior
No reuse,
maintenance hell
Flashcard 1 (Core Principle - Page 9)
Q: What is the first design principle introduced, and how does it address the duck problem?
A:
Principle: “Identify the aspects that vary and separate them from what stays the same.”
Application:
Varies: Fly/quack behaviors
Stable: Swim/display methods
Key Insight: Encapsulate fly/quack into separate classes to isolate changes.
Quote:
“Take the parts that vary and encapsulate them so later you can alter them without affecting stable parts.”
Flashcard 2 (Encapsulation - Page 9)
Q: How does encapsulation enable flexibility in the duck design?
A:
Isolates change: Modifying fly behavior (e.g., adding FlyRocketPowered) doesn’t touch Duck classes.
Extensible: New behaviors can be added without rewriting existing code.
Visual:
Duck → Delegates to → FlyBehavior (encapsulated)
Flashcard 3 (Second Principle - Page 11)
Q: What does “Program to an interface, not an implementation” mean?
A:
Declare variables as interface types (e.g., FlyBehavior)
Avoid concrete dependencies: Ducks depend on FlyBehavior interface, not FlyWithWings class.
Code Contrast:
// BAD: Tied to concrete class
FlyWithWings f = new FlyWithWings();
// GOOD: Uses interface
FlyBehavior f = new FlyWithWings();
Flashcard 4 (Interface vs. Implementation - Page 12)
Q: Why is the FlyBehavior interface superior to inheritance or Java interfaces?
A:
Polymorphism: Ducks work with any FlyBehavior implementation.
Reuse: FlyWithWings can be shared across ducks (unlike Java interfaces).
Key Quote:
“The declared type should be a supertype (interface/abstract class) so objects can be any concrete implementation.”
Flashcard 5 (Design Impact - Page 11-12)
Q: How do these principles transform the duck design?
A:
Behaviors become families of algorithms:
FlyBehavior: FlyWithWings, FlyNoWay, etc.
Ducks delegate behaviors:
performQuack() → Calls quackBehavior.quack()
Runtime flexibility: Behaviors can be swapped dynamically.
Diagram:
Duck → HAS-A → FlyBehavior (interface)
↑
FlyWithWings (implementation)
Flashcard 6 (Polymorphism Example - Page 12)
Q: How does the Animal example illustrate “programming to a supertype”?
A:
Bad: Dog d = new Dog(); ← Locks code to Dog
Good: Animal a = new Dog(); ← Works with any Animal subtype
Critical Idea:
“We don’t care about the concrete type—only that it can makeSound().”
Flashcard 7 (Terminology - Page 12)
Q: Clarify the overloaded term “interface” in design principles.
A:
Conceptual: “Program to a supertype” (interface/abstract class)
Java: interface keyword is one way to achieve it.
Key Distinction:
Goal: Exploit polymorphism by coding to abstractions.
Flashcard 8 (Behavior Classes - Page 11)
Q: Why are fly/quack behaviors now separate classes?
A:
Reuse: FlyWithWings can be used by MallardDuck, RedheadDuck, etc.
Single Responsibility: Each class handles one behavior variation.
Example:
Quack: Normal quacking
Squeak: Rubber ducks
MuteQuack: Decoys
Flashcard 9 (Principle to Pattern - Page 12)
Q: How do these principles lead to the Strategy Pattern?
A:
Encapsulate variations → Separate fly/quack behaviors
Program to interfaces → FlyBehavior/QuackBehavior
Composition over inheritance → Ducks have behaviors, don’t inherit them.
Pattern Preview:
“Strategy defines a family of algorithms, encapsulates each, and makes them interchangeable.”
Summary Table: Principles
Principle Key Action Duck Example
Encapsulate what varies Separate fly/quack Extract to FlyBehavior
Program to interfaces Depend on FlyBehavior Not FlyWithWings
Favor composition (implied, Page 11) Ducks have behaviors HAS-A over IS-A
Flashcard 1 (Behavior Interfaces - Page 13)
Q: What are the two core behavior interfaces and their methods?
A:
FlyBehavior → fly()
QuackBehavior → quack()
Key Point:
Each interface represents a family of algorithms (e.g., flying/quacking variations).
Flashcard 2 (FlyBehavior Implementations - Page 13)
Q: Name and describe the two FlyBehavior concrete classes.
A:
FlyWithWings: Implements flying for ducks with wings (I’m flying!!)
FlyNoWay: For non-flying ducks (I can’t fly).
Code:
public class FlyWithWings implements FlyBehavior {
public void fly() { System.out.println(“I’m flying!!”); }
}
Flashcard 3 (QuackBehavior Implementations - Page 13)
Q: List the three QuackBehavior implementations and their purposes.
A:
Quack: Normal duck quack
Squeak: Rubber duck squeak
MuteQuack: Silent (for decoys).
Hierarchy:
QuackBehavior (interface)
├─ Quack
├─ Squeak
└─ MuteQuack