Skip to content

Commit 0c47239

Browse files
authored
Merge pull request #1 from ahucoder/dev
The Strategy Pattern
2 parents 9c65088 + 2ef3f66 commit 0c47239

File tree

12 files changed

+201
-0
lines changed

12 files changed

+201
-0
lines changed

pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,18 @@
1414
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1515
</properties>
1616

17+
<dependencies>
18+
<dependency>
19+
<groupId>org.projectlombok</groupId>
20+
<artifactId>lombok</artifactId>
21+
<version>1.18.36</version>
22+
<scope>provided</scope>
23+
</dependency>
24+
<dependency>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-starter-web</artifactId>
27+
<version>3.4.5</version>
28+
</dependency>
29+
</dependencies>
30+
1731
</project>

src/main/java/strategy/App.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package strategy;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class App {
8+
public static void main(String[] args) {
9+
SpringApplication.run(App.class);
10+
}
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package strategy.annotation;
2+
3+
import strategy.enums.AttackType;
4+
5+
import java.lang.annotation.ElementType;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
@Target(ElementType.TYPE)
11+
@Retention(RetentionPolicy.RUNTIME)
12+
public @interface SupportAttackType {
13+
AttackType value();
14+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package strategy.constant;
2+
3+
public class AttackTypeValue {
4+
public static final int PHYSIC_ATTACK_VALUE = 1;
5+
public static final int MAGIC_ATTACK_VALUE = 2;
6+
public static final int POISON_ATTACK_VALUE = 3;
7+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package strategy.controller;
2+
3+
import jakarta.annotation.PostConstruct;
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
import org.springframework.web.bind.annotation.PathVariable;
7+
import org.springframework.web.bind.annotation.RestController;
8+
import strategy.annotation.SupportAttackType;
9+
import strategy.enums.AttackType;
10+
import strategy.service.AttackService;
11+
import strategy.service.DefaultAttack;
12+
13+
import java.util.List;
14+
import java.util.Map;
15+
import java.util.function.Function;
16+
import java.util.stream.Collectors;
17+
18+
@RestController
19+
public class AttackController {
20+
private Map<AttackType, AttackService> attackServiceMap;
21+
22+
@Autowired
23+
private DefaultAttack defaultAttackService;
24+
25+
// @Autowired
26+
// private List<AttackService> attackServices;
27+
28+
@GetMapping("/attack/{type}")
29+
public String attack(@PathVariable(value = "type") int type) {
30+
AttackType attackType = AttackType.typeOf(type);
31+
AttackService attackService = attackServiceMap.getOrDefault(attackType, defaultAttackService);
32+
return attackService.attack();
33+
}
34+
35+
@Autowired
36+
private void setAttackServiceMap(List<AttackService> attackServiceList) {
37+
this.attackServiceMap = attackServiceList.stream()
38+
.filter(attackService -> attackService.getClass().isAnnotationPresent(SupportAttackType.class))
39+
.collect(Collectors.toMap(AttackService::getAttackTypeByService, Function.identity()));
40+
if (this.attackServiceMap.size() != AttackType.values().length) {
41+
throw new IllegalArgumentException("some attack types are not supported");
42+
}
43+
}
44+
45+
//The following code completes the same task as setAttackServiceMap(List)
46+
/*@PostConstruct
47+
private void initAttackServiceMap() {
48+
this.attackServiceMap = attackServices.stream()
49+
.filter(attackService -> attackService.getClass().isAnnotationPresent(SupportAttackType.class))
50+
.collect(Collectors.toMap(AttackService::getAttackTypeByService, Function.identity()));
51+
if (this.attackServiceMap.size() != AttackType.values().length) {
52+
throw new IllegalArgumentException("some attack types are not supported");
53+
}
54+
}*/
55+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package strategy.enums;
2+
3+
import java.util.Arrays;
4+
import java.util.function.IntPredicate;
5+
6+
import static strategy.constant.AttackTypeValue.*;
7+
8+
public enum AttackType {
9+
PhysicalAttack(attackType -> attackType == PHYSIC_ATTACK_VALUE),
10+
MagicAttack(attackType -> attackType == MAGIC_ATTACK_VALUE),
11+
PoisonAttack(attackType -> attackType == POISON_ATTACK_VALUE),
12+
;
13+
14+
private final IntPredicate route;
15+
16+
AttackType(IntPredicate route) {
17+
this.route = route;
18+
}
19+
20+
public static AttackType typeOf(int attackType) {
21+
return Arrays.stream(values())
22+
.filter(value -> value.route.test(attackType))
23+
.findFirst()
24+
.orElse(null);
25+
}
26+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package strategy.service;
2+
3+
import strategy.annotation.SupportAttackType;
4+
import strategy.enums.AttackType;
5+
6+
public interface AttackService {
7+
8+
String attack();
9+
10+
default AttackType getAttackTypeByService() {
11+
SupportAttackType annotation = this.getClass().getAnnotation(SupportAttackType.class);
12+
if (annotation != null) {
13+
return annotation.value();
14+
}
15+
throw new IllegalStateException("AttackService implementation must be annotated with @SupportAttackType");
16+
}
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package strategy.service;
2+
3+
import org.springframework.stereotype.Service;
4+
5+
@Service
6+
public class DefaultAttack implements AttackService {
7+
@Override
8+
public String attack() {
9+
return "No Attack";
10+
}
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package strategy.service;
2+
3+
import org.springframework.stereotype.Service;
4+
import strategy.annotation.SupportAttackType;
5+
import strategy.enums.AttackType;
6+
7+
@Service
8+
@SupportAttackType(AttackType.MagicAttack)
9+
public class MagicAttack implements AttackService {
10+
@Override
11+
public String attack() {
12+
System.out.println("Magic Attack");
13+
return "Magic Attack";
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package strategy.service;
2+
3+
import org.springframework.stereotype.Service;
4+
import strategy.annotation.SupportAttackType;
5+
import strategy.enums.AttackType;
6+
7+
@Service
8+
@SupportAttackType(AttackType.PhysicalAttack)
9+
public class PhysicalAttack implements AttackService {
10+
@Override
11+
public String attack() {
12+
System.out.println("Physical Attack");
13+
return "Physical Attack";
14+
}
15+
}

0 commit comments

Comments
 (0)