diff --git a/pom.xml b/pom.xml
index e7849da..5c2a7e1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,4 +14,18 @@
UTF-8
+
+
+ org.projectlombok
+ lombok
+ 1.18.36
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ 3.4.5
+
+
+
\ No newline at end of file
diff --git a/src/main/java/strategy/App.java b/src/main/java/strategy/App.java
new file mode 100644
index 0000000..7bee699
--- /dev/null
+++ b/src/main/java/strategy/App.java
@@ -0,0 +1,11 @@
+package strategy;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class App {
+ public static void main(String[] args) {
+ SpringApplication.run(App.class);
+ }
+}
diff --git a/src/main/java/strategy/annotation/SupportAttackType.java b/src/main/java/strategy/annotation/SupportAttackType.java
new file mode 100644
index 0000000..eb358be
--- /dev/null
+++ b/src/main/java/strategy/annotation/SupportAttackType.java
@@ -0,0 +1,14 @@
+package strategy.annotation;
+
+import strategy.enums.AttackType;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SupportAttackType {
+ AttackType value();
+}
diff --git a/src/main/java/strategy/constant/AttackTypeValue.java b/src/main/java/strategy/constant/AttackTypeValue.java
new file mode 100644
index 0000000..4d75e84
--- /dev/null
+++ b/src/main/java/strategy/constant/AttackTypeValue.java
@@ -0,0 +1,7 @@
+package strategy.constant;
+
+public class AttackTypeValue {
+ public static final int PHYSIC_ATTACK_VALUE = 1;
+ public static final int MAGIC_ATTACK_VALUE = 2;
+ public static final int POISON_ATTACK_VALUE = 3;
+}
diff --git a/src/main/java/strategy/controller/AttackController.java b/src/main/java/strategy/controller/AttackController.java
new file mode 100644
index 0000000..973daa0
--- /dev/null
+++ b/src/main/java/strategy/controller/AttackController.java
@@ -0,0 +1,55 @@
+package strategy.controller;
+
+import jakarta.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+import strategy.annotation.SupportAttackType;
+import strategy.enums.AttackType;
+import strategy.service.AttackService;
+import strategy.service.DefaultAttack;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@RestController
+public class AttackController {
+ private Map attackServiceMap;
+
+ @Autowired
+ private DefaultAttack defaultAttackService;
+
+// @Autowired
+// private List attackServices;
+
+ @GetMapping("/attack/{type}")
+ public String attack(@PathVariable(value = "type") int type) {
+ AttackType attackType = AttackType.typeOf(type);
+ AttackService attackService = attackServiceMap.getOrDefault(attackType, defaultAttackService);
+ return attackService.attack();
+ }
+
+ @Autowired
+ private void setAttackServiceMap(List attackServiceList) {
+ this.attackServiceMap = attackServiceList.stream()
+ .filter(attackService -> attackService.getClass().isAnnotationPresent(SupportAttackType.class))
+ .collect(Collectors.toMap(AttackService::getAttackTypeByService, Function.identity()));
+ if (this.attackServiceMap.size() != AttackType.values().length) {
+ throw new IllegalArgumentException("some attack types are not supported");
+ }
+ }
+
+ //The following code completes the same task as setAttackServiceMap(List)
+ /*@PostConstruct
+ private void initAttackServiceMap() {
+ this.attackServiceMap = attackServices.stream()
+ .filter(attackService -> attackService.getClass().isAnnotationPresent(SupportAttackType.class))
+ .collect(Collectors.toMap(AttackService::getAttackTypeByService, Function.identity()));
+ if (this.attackServiceMap.size() != AttackType.values().length) {
+ throw new IllegalArgumentException("some attack types are not supported");
+ }
+ }*/
+}
diff --git a/src/main/java/strategy/enums/AttackType.java b/src/main/java/strategy/enums/AttackType.java
new file mode 100644
index 0000000..5726dfd
--- /dev/null
+++ b/src/main/java/strategy/enums/AttackType.java
@@ -0,0 +1,26 @@
+package strategy.enums;
+
+import java.util.Arrays;
+import java.util.function.IntPredicate;
+
+import static strategy.constant.AttackTypeValue.*;
+
+public enum AttackType {
+ PhysicalAttack(attackType -> attackType == PHYSIC_ATTACK_VALUE),
+ MagicAttack(attackType -> attackType == MAGIC_ATTACK_VALUE),
+ PoisonAttack(attackType -> attackType == POISON_ATTACK_VALUE),
+ ;
+
+ private final IntPredicate route;
+
+ AttackType(IntPredicate route) {
+ this.route = route;
+ }
+
+ public static AttackType typeOf(int attackType) {
+ return Arrays.stream(values())
+ .filter(value -> value.route.test(attackType))
+ .findFirst()
+ .orElse(null);
+ }
+}
diff --git a/src/main/java/strategy/service/AttackService.java b/src/main/java/strategy/service/AttackService.java
new file mode 100644
index 0000000..59ddc35
--- /dev/null
+++ b/src/main/java/strategy/service/AttackService.java
@@ -0,0 +1,17 @@
+package strategy.service;
+
+import strategy.annotation.SupportAttackType;
+import strategy.enums.AttackType;
+
+public interface AttackService {
+
+ String attack();
+
+ default AttackType getAttackTypeByService() {
+ SupportAttackType annotation = this.getClass().getAnnotation(SupportAttackType.class);
+ if (annotation != null) {
+ return annotation.value();
+ }
+ throw new IllegalStateException("AttackService implementation must be annotated with @SupportAttackType");
+ }
+}
diff --git a/src/main/java/strategy/service/DefaultAttack.java b/src/main/java/strategy/service/DefaultAttack.java
new file mode 100644
index 0000000..8c9c224
--- /dev/null
+++ b/src/main/java/strategy/service/DefaultAttack.java
@@ -0,0 +1,11 @@
+package strategy.service;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class DefaultAttack implements AttackService {
+ @Override
+ public String attack() {
+ return "No Attack";
+ }
+}
diff --git a/src/main/java/strategy/service/MagicAttack.java b/src/main/java/strategy/service/MagicAttack.java
new file mode 100644
index 0000000..2300395
--- /dev/null
+++ b/src/main/java/strategy/service/MagicAttack.java
@@ -0,0 +1,15 @@
+package strategy.service;
+
+import org.springframework.stereotype.Service;
+import strategy.annotation.SupportAttackType;
+import strategy.enums.AttackType;
+
+@Service
+@SupportAttackType(AttackType.MagicAttack)
+public class MagicAttack implements AttackService {
+ @Override
+ public String attack() {
+ System.out.println("Magic Attack");
+ return "Magic Attack";
+ }
+}
diff --git a/src/main/java/strategy/service/PhysicalAttack.java b/src/main/java/strategy/service/PhysicalAttack.java
new file mode 100644
index 0000000..3356a6d
--- /dev/null
+++ b/src/main/java/strategy/service/PhysicalAttack.java
@@ -0,0 +1,15 @@
+package strategy.service;
+
+import org.springframework.stereotype.Service;
+import strategy.annotation.SupportAttackType;
+import strategy.enums.AttackType;
+
+@Service
+@SupportAttackType(AttackType.PhysicalAttack)
+public class PhysicalAttack implements AttackService {
+ @Override
+ public String attack() {
+ System.out.println("Physical Attack");
+ return "Physical Attack";
+ }
+}
diff --git a/src/main/java/strategy/service/PoisonAttack.java b/src/main/java/strategy/service/PoisonAttack.java
new file mode 100644
index 0000000..4a55d3e
--- /dev/null
+++ b/src/main/java/strategy/service/PoisonAttack.java
@@ -0,0 +1,15 @@
+package strategy.service;
+
+import org.springframework.stereotype.Service;
+import strategy.annotation.SupportAttackType;
+import strategy.enums.AttackType;
+
+@Service
+@SupportAttackType(value = AttackType.PoisonAttack)
+public class PoisonAttack implements AttackService {
+ @Override
+ public String attack() {
+ System.out.println("Poison Attack");
+ return "Poison Attack";
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..c57fe8b
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.application.name=JavaDesignPatterns
\ No newline at end of file