1.简介
在真实开发中,我们经常需要处理不同类型的对象,但是对他们的操作是相同或者类似的,在这种场景下,策略模式就派上用场啦,我之前也看过不少文章,但是看的云里雾里,看完还是不知道怎么用,那么,在这篇文章中,我也不写理论的东西,直接上代码,和大家一起交流,一起学习。
2.模拟场景
我们在系统中展示了一些图片、视频、活动等,当用户点击之后,我们需要把这个视频或者这个活动的浏览量增加1,同时,这些数据都存储在各自的数据表中,也就是说,我们在更新浏览量时,需要更新不同的表,你不可能用if else 去搞吧,哈哈哈。这就是对不同的类型进行相同的操作,那就很契合策略模式呀。哈哈哈,直接上代码吧。
3. Contorller层
我们先看一下控制层,这是接口的入口,这个没什么说的,就是常规代码:
// ViewCountController.java
@Validated
@RestController
@RequestMapping("/view-count")
@RequiredArgsConstructor
public class ViewCountController {
private final ViewCountContext viewCountContext;
@PostMapping("/increase")
@Operation(summary = "浏览量递增", description = "该接口用于用户点击相应业务时,增加浏览量")
public GenericResponseEntity<Boolean> increaseViewCount(@RequestBody @Valid ViewCountIncreaseDto request) {
viewCountContext.increaseViewCount(request);
return GenericResponseEntity.success(true);
}
}
简单说一下其中的注解,@Operation 这个是OpenSwagger的注解,其他的就是常规注解啦。
4.定义浏览量类型枚举ViewCountTypeEnum
方便统一管理
这个枚举类是干啥的呢? 我们不是有很多类型的业务嘛,这个枚举就是用来定义不同的业务类型,然后开放一个业务类型的字段给前端,前端就通过这个字段告诉我们用户点击的是哪个业务,后端就可以根据传递过来的值拿到对应的业务枚举,然后就可以根据策略执行具体的代码啦。
// ViewCountTypeEnum.java
@Getter
public enum ViewCountTypeEnum {
ACTIVITY_VIEW("activityView", "活动浏览量"),
PICTURE_VIEW("pictureView", "图片浏览量"),
VIDEO_VIEW("videoView", "视频浏览量");
private final String type;
private final String desc;
ViewCountTypeEnum(String type, String desc) {
this.type = type;
this.desc = desc;
}
public String getType() {
return this.type;
}
public String getDesc() {
return this.desc;
}
public static ViewCountTypeEnum getCommentTypeEnum(String type) {
for (ViewCountTypeEnum viewCountTypeEnum : ViewCountTypeEnum.values()) {
if (viewCountTypeEnum.getType().equals(type)) {
return viewCountTypeEnum;
}
}
throw new IllegalArgumentException("无效的type值: " + type);
}
}
5. 定义一个接口ViewCountStrategy
作为浏览量递增策略的通用接口:
这儿有两个接口,一个是浏览量递增策略的通用接口,一个是获取具体业务枚举的接口。
// ViewCountStrategy.java
public interface ViewCountStrategy {
// 通用接口
void increaseViewCount(Long id);
// 根据前端传递的值,获取具体的类型
String getViewCountType();
}
6.具体的浏览量递增策略由实现了 ViewCountStrategy 接口的具体业务类来完成,如下三个类型的业务
下面就是具体业务执行 浏览量递增的逻辑啦。
6.1.图片类型
public class PictureViewCountStrategy implements ViewCountStrategy {
@Resource
private SharedEStationsPictureMapper pictureMapper;
@Override
public void increaseViewCount(Long id) {
SharedEStationsPicture picture = pictureMapper.selectById(id);
if (null != picture) {
picture.setViews(picture.getViews() + 1);
pictureMapper.updateById(picture);
}
}
@Override
public String getViewCountType() {
return ViewCountTypeEnum.PICTURE_VIEW.getType();
}
}
6.2.视频类型
@Component
public class VideoViewCountStrategy implements ViewCountStrategy {
@Resource
private SharedEStationsVideoMapper videoMapper;
@Override
public void increaseViewCount(Long id) {
SharedEStationsVideo video = videoMapper.selectById(id);
if (null != video) {
video.setViews(video.getViews() + 1);
videoMapper.updateById(video);
}
}
@Override
public String getViewCountType() {
return ViewCountTypeEnum.VIDEO_VIEW.getType();
}
}
6.3.活动类型
@Component
public class ActivityViewCountStrategy implements ViewCountStrategy {
@Resource
private SharedEStationsActivityMapper activityMapper;
@Override
public void increaseViewCount(Long id) {
SharedEStationsActivity activity = activityMapper.selectById(id);
if (activity != null) {
activity.setViews(activity.getViews() + 1);
activityMapper.updateById(activity);
}
}
@Override
public String getViewCountType() {
return ViewCountTypeEnum.ACTIVITY_VIEW.getType();
}
}
7. 最后定义了一个上下文类ViewCountContext
用来协调不同类型的浏览量递增的策略:
这个就是协调各业务类型的策略上下文。
// ViewCountContext.java
@Component
public class ViewCountContext {
private final Map<String, ViewCountStrategy> strategies = new ConcurrentHashMap<>();
@Autowired
public ViewCountContext(List<ViewCountStrategy> strategyList) {
strategyList.forEach(strategy -> strategies.put(strategy.getViewCountType(), strategy));
}
public void increaseViewCount(ViewCountIncreaseDto request) {
ViewCountStrategy strategy = strategies.get(request.getViewCountType());
if (strategy != null) {
strategy.increaseViewCount(request.getId());
}
}
}
8. 实际使用
对于图片类型的浏览量递增
{
"viewCountType": "pictureView",
"id": 1
}
9.总结
通过使用策略模式,我们成功地将不同类型的浏览量递增操作进行了解耦,使得系统更加灵活和可维护。每个具体业务类都可以独立地进行扩展和修改,而不会影响到其他部分的代码。
以上就是一个简单的Spring Boot + 策略模式的实战示例。希望能帮到大家,欢迎大家多多交流。