diff --git a/strategy/README.md b/strategy/README.md index b70ed94f2..95a33a62a 100644 --- a/strategy/README.md +++ b/strategy/README.md @@ -3,36 +3,39 @@ title: Strategy category: Behavioral language: en tag: - - Gang of Four + - Decoupling + - Extensibility + - Gang of Four + - Interface + - Polymorphism --- ## Also known as -Policy +* Policy ## Intent -Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets -the algorithm vary independently of the clients that use it. +Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently of the clients that use it. ## Explanation Real-world example -> Slaying dragons is a dangerous job. With experience, it becomes easier. Veteran -> dragonslayers have developed different fighting strategies against different types of dragons. +> An analogous real-world example of the Strategy design pattern is the navigation systems in cars. Different navigation algorithms (such as shortest route, fastest route, and scenic route) can be used to determine the best path from one location to another. Each algorithm encapsulates a specific strategy for calculating the route. The user (client) can switch between these algorithms based on their preferences without changing the navigation system itself. This allows for flexible and interchangeable navigation strategies within the same system. In plain words -> Strategy pattern allows choosing the best-suited algorithm at runtime. +> Strategy pattern allows choosing the best-suited algorithm at runtime. Wikipedia says -> In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral -> software design pattern that enables selecting an algorithm at runtime. +> In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. **Programmatic Example** +Slaying dragons is a dangerous job. With experience, it becomes easier. Veteran dragonslayers have developed different fighting strategies against different types of dragons. + Let's first introduce the dragon-slaying strategy interface and its implementations. ```java @@ -70,8 +73,7 @@ public class SpellStrategy implements DragonSlayingStrategy { } ``` -And here is the mighty dragonslayer, who can pick his fighting strategy based on the -opponent. +And here is the mighty dragonslayer, who can pick his fighting strategy based on the opponent. ```java public class DragonSlayer { @@ -117,71 +119,51 @@ Program output: You cast the spell of disintegration and the dragon vaporizes in a pile of dust! ``` -What's more, the lambda expressions in Java 8 provides another approach for the implementation: - -```java -public class LambdaStrategy { - - private static final Logger LOGGER = LoggerFactory.getLogger(LambdaStrategy.class); - - public enum Strategy implements DragonSlayingStrategy { - MeleeStrategy(() -> LOGGER.info( - "With your Excalibur you severe the dragon's head!")), - ProjectileStrategy(() -> LOGGER.info( - "You shoot the dragon with the magical crossbow and it falls dead on the ground!")), - SpellStrategy(() -> LOGGER.info( - "You cast the spell of disintegration and the dragon vaporizes in a pile of dust!")); - - private final DragonSlayingStrategy dragonSlayingStrategy; - - Strategy(DragonSlayingStrategy dragonSlayingStrategy) { - this.dragonSlayingStrategy = dragonSlayingStrategy; - } - - @Override - public void execute() { - dragonSlayingStrategy.execute(); - } - } -} -``` - -And here's the dragonslayer in action. - -```java - LOGGER.info("Green dragon spotted ahead!"); - dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MeleeStrategy); - dragonSlayer.goToBattle(); - LOGGER.info("Red dragon emerges."); - dragonSlayer.changeStrategy(LambdaStrategy.Strategy.ProjectileStrategy); - dragonSlayer.goToBattle(); - LOGGER.info("Black dragon lands before you."); - dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SpellStrategy); - dragonSlayer.goToBattle(); -``` - -The program output is the same as the above one. - ## Class diagram -![alt text](./etc/strategy_urm.png "Strategy") +![Strategy](./etc/strategy_urm.png "Strategy") ## Applicability -Use the Strategy pattern when +Use the Strategy pattern when: -* Many related classes differ only in their behavior. Strategies provide a way to configure a class either one of many behaviors -* You need different variants of an algorithm. for example, you might define algorithms reflecting different space/time trade-offs. Strategies can be used when these variants are implemented as a class hierarchy of algorithms -* An algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex algorithm-specific data structures -* A class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move the related conditional branches into their own Strategy class +* You need to use different variants of an algorithm within an object and want to switch algorithms at runtime. +* There are multiple related classes that differ only in their behavior. +* An algorithm uses data that clients shouldn't know about. +* A class defines many behaviors and these appear as multiple conditional statements in its operations. -## Tutorial +## Tutorial -* [Strategy Pattern Tutorial](https://www.journaldev.com/1754/strategy-design-pattern-in-java-example-tutorial) +* [Strategy Pattern Tutorial - Digital Ocean](https://www.digitalocean.com/community/tutorials/strategy-design-pattern-in-java-example-tutorial) + +## Known Uses + +* Java's `java.util.Comparator` interface is a common example of the Strategy pattern. +* In GUI frameworks, layout managers (such as those in Java's AWT and Swing) are strategies. + +## Consequences + +Benefits: + +* Families of related algorithms are reused. +* An alternative to subclassing for extending behavior. +* Avoids conditional statements for selecting desired behavior. +* Allows clients to choose algorithm implementation. + +Trade-offs: + +* Clients must be aware of different Strategies. +* Increase in the number of objects. + +## Related patterns + +* [State](https://java-design-patterns.com/patterns/state/): Similar in structure but used to represent state-dependent behavior rather than interchangeable algorithms. +* [Decorator](https://java-design-patterns.com/patterns/decorator/): Enhances an object without changing its interface but is more concerned with responsibilities than algorithms. ## Credits -* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59) -* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b) -* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b) -* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7) +* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI) +* [Functional Programming in Java](https://amzn.to/3JUIc5Q) +* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq) +* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR) +* [Refactoring to Patterns](https://amzn.to/3VOO4F5) diff --git a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java index c01b9d3be..ae05ea9ae 100644 --- a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java +++ b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java @@ -91,7 +91,7 @@ class DragonSlayingStrategyTest { assertEquals(1, appender.getLogSize()); } - private class InMemoryAppender extends AppenderBase { + private static class InMemoryAppender extends AppenderBase { private final List log = new LinkedList<>(); public InMemoryAppender() {