【设计模式】SpringBoot优雅使用策略模式

一、简述

引用:【设计模式】SpringBoot优雅使用策略模式

策略模式有3种角色,分别为:选择器抽象策略策略实例
其中选择器selector又被称为上下文context,其作用为通过不同的标识来获取对应的策略实例。策略实例就是封装不同算法的实例对象实例对象&spm=1001.2101.3001.7020),而抽象策略就是策略实例的顶层接口。

简单类图大概就是这个样子:

二、实现

1、定义对象

1
2
3
4
5
6
7
8
9
/**
* 定义beanName需要注意属性顺序
*/
@Data
public class User {
private String name;
private Integer age;
private Boolean isSp;
}

2、抽象策略处理器

1
2
3
4
5
6
7
8
9
10
11
public interface TestService {

//方法策略
public void doMethod(User user);

//可以定义共同方法
default void spHandle(User user){
user.setAge(user.getAge()+1);
}

}

3、定义策略选择器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Service
public class TestServiceFactory {

@Resource
private Map<String, TestService> services;

/**
* 获取service实例
*
* @param user
* @return
*/
public TestService instance(User user) {
try {
//自定义beanName处理,此处为拼接对象属性,空值不参与拼接,{ _ }分隔
String beanName = StringUtils.concatenateFields(user, "_");
if (services.containsKey(beanName)) {
return services.get(beanName);
}
//可以定义一个默认策略
return services.get("default");
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

}

对象字段拼接字符串工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class StringUtils extends StrUtil {

/**
* 将对象的所有非空字段拼接成一个字符串。
* @param obj 要转换的对象
* @param separator 字段之间的分隔符
* @return 字符串表示
* @throws IllegalAccessException 如果无法访问字段抛出此异常
*/
public static String concatenateFields(Object obj, String separator) throws IllegalAccessException {
StringBuilder sb = new StringBuilder();
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();

// 遍历所有字段
for (Field field : fields) {
// 设置为可访问,以便能访问私有变量
field.setAccessible(true);
Object value = field.get(obj);

// 检查是否为空或空白字符串
if (value != null && !(value instanceof String && ((String) value).trim().isEmpty())) {
if (sb.length() > 0) {
sb.append(separator);
}
sb.append(value.toString());
}
}
return sb.toString();
}

}

4、策略实现类

注意:此处定义beanName时会按照对象属性的顺序进行拼接

默认策略实现

1
2
3
4
5
6
7
8
9
10
@Service("default")
public class DefaultTestServiceImpl implements TestService {

@Override
public void doMethod(User user) {
spHandle(user);
System.out.println("DefaultTestServiceImpl");
}

}

实现策略A

1
2
3
4
5
6
7
8
9
10
@Service("sherlock_18_false")
public class ATestServiceImpl implements TestService {

@Override
public void doMethod(User user) {
spHandle(user);
System.out.println("DefaultTestServiceImpl");
}

}

实现策略B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Service("sherlock_true")
public class BTestServiceImpl implements TestService {

@Override
public void doMethod(User user) {
spHandle(user);
System.out.println("DefaultTestServiceImpl");
}

@Override
public void spHandle(User user) {
// 自定义重写方法
}

}