Repository: iluwatar/java-design-patterns
Issue: Functional implementation of Strategy pattern
Labels: epic: pattern
type: enhancement

Strategy has been implemented using Java classes. In modern Java about the same can be achieved by passing methods. Let's amend the Strategy example with functional style implementation.

Issue comments:
Please assign to me thx
Ok @maheshsv 
Do we need to implement Strategy Pattern using Lambda Expressions in Java 8
Yes, that would be great addition to this pattern example
ok can i create a branch and work on it, ?
Go ahead @maheshsv 
Hi, I want to solve this issue if it is still open.
May I? @iluwatar 
There's a pull request from @Tubaleviao but haven't heard of him for a while
Go ahead @ignite1771 , I'm in a quest right now
Ok, I will work on this and send a PR to fix this issue.
Thanks @ignite1771, looking forward to it

Pull request review comments:

Patch that resolved the issue:
diff --git a/strategy/README.md b/strategy/README.md
index b2330ceb84ce..2d2cbf9c4823 100644
--- a/strategy/README.md
+++ b/strategy/README.md
@@ -122,6 +122,51 @@ Program output:
     You cast the spell of disintegration and the dragon vaporizes in a pile of dust!    
 ```
 
+What's more, the new feature 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();
+```
+
+Program output is the same as above one.
+
 ## Class diagram
 
 ![alt text](./etc/strategy_urm.png "Strategy")
diff --git a/strategy/etc/strategy.urm.puml b/strategy/etc/strategy.urm.puml
index 8b9daabb9db4..d9b9aa526d9a 100644
--- a/strategy/etc/strategy.urm.puml
+++ b/strategy/etc/strategy.urm.puml
@@ -14,6 +14,19 @@ package com.iluwatar.strategy {
   interface DragonSlayingStrategy {
     + execute() {abstract}
   }
+  class LambdaStrategy {
+    - LOGGER : Logger {static}
+    + LambdaStrategy()
+  }
+  enum Strategy {
+    + MeleeStrategy {static}
+    + ProjectileStrategy {static}
+    + SpellStrategy {static}
+    - dragonSlayingStrategy : DragonSlayingStrategy
+    + execute()
+    + valueOf(name : String) : Strategy {static}
+    + values() : Strategy[] {static}
+  }
   class MeleeStrategy {
     - LOGGER : Logger {static}
     + MeleeStrategy()
@@ -30,7 +43,10 @@ package com.iluwatar.strategy {
     + execute()
   }
 }
+Strategy ..+ LambdaStrategy
+Strategy -->  "-dragonSlayingStrategy" DragonSlayingStrategy
 DragonSlayer -->  "-strategy" DragonSlayingStrategy
+Strategy ..|> DragonSlayingStrategy 
 MeleeStrategy ..|> DragonSlayingStrategy 
 ProjectileStrategy ..|> DragonSlayingStrategy 
 SpellStrategy ..|> DragonSlayingStrategy 
diff --git a/strategy/src/main/java/com/iluwatar/strategy/App.java b/strategy/src/main/java/com/iluwatar/strategy/App.java
index c526c791787d..6313087b0bff 100644
--- a/strategy/src/main/java/com/iluwatar/strategy/App.java
+++ b/strategy/src/main/java/com/iluwatar/strategy/App.java
@@ -45,7 +45,7 @@ public class App {
   
   /**
    * Program entry point.
-   * 
+   *
    * @param args command line args
    */
   public static void main(String[] args) {
@@ -60,7 +60,7 @@ public static void main(String[] args) {
     dragonSlayer.changeStrategy(new SpellStrategy());
     dragonSlayer.goToBattle();
 
-    // Java 8 Strategy pattern
+    // Java 8 functional implementation Strategy pattern
     LOGGER.info("Green dragon spotted ahead!");
     dragonSlayer = new DragonSlayer(
         () -> LOGGER.info("With your Excalibur you severe the dragon's head!"));
@@ -73,5 +73,16 @@ public static void main(String[] args) {
     dragonSlayer.changeStrategy(() -> LOGGER.info(
         "You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"));
     dragonSlayer.goToBattle();
+
+    // Java 8 lambda implementation with enum Strategy pattern
+    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();
   }
 }
diff --git a/strategy/src/main/java/com/iluwatar/strategy/LambdaStrategy.java b/strategy/src/main/java/com/iluwatar/strategy/LambdaStrategy.java
new file mode 100644
index 000000000000..d7480601738b
--- /dev/null
+++ b/strategy/src/main/java/com/iluwatar/strategy/LambdaStrategy.java
@@ -0,0 +1,29 @@
+package com.iluwatar.strategy;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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();
+    }
+  }
+}


Test patch: