文章目录
创建design-demo项目
项目代码:https://gitee.com/java_wxid/java_wxid/tree/master/demo/design-demo
项目结构如下(示例):
需求分析
责任链模式核心功能:允许规则实时增减和顺序调整。
如果按照传统模式开发,这里难以满足上述规则实时增减和顺序调整,其次过滤规则有可能根据产品需求灵活变动,一旦发生变动就会对业务层代码进行修改,从而可能影响之前开发好的业务逻辑。
创建UserController
代码如下(示例):
package com.example.designdemo.controller;
import com.example.designdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 19:26
* @Description:
*/
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/suggest")
public List<String> suggestRequirement(@RequestParam String username) {
return userService.suggestRequirement(username);
}
}
创建AbstractSuggestRequirementHandler
代码如下(示例):
package com.example.designdemo.handler;
import com.example.designdemo.pojo.UserInfo;
import java.util.List;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 19:26
* @Description:
*/
public abstract class AbstractSuggestRequirementHandler {
abstract void processHandler(UserInfo userInfo, List<String> suggestLists);
}
创建CityCheckHandler
代码如下(示例):
package com.example.designdemo.handler;
import com.example.designdemo.pojo.UserInfo;
import java.util.List;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 19:26
* @Description:用户所在城市是否满足业务投放城市
*/
public class CityCheckHandler extends AbstractSuggestRequirementHandler{
@Override
public void processHandler(UserInfo userInfo, List<String> suggestLists) {
//通过获取 userinfo 的 city 属性
String city = userInfo.getCity();
// 通过city 和 之前保留的 4 个 业务信息进行对比。然后筛选出剩余的 3 个 业务投放
suggestLists.remove("1");
}
}
创建NewCheckHandler
代码如下(示例):
package com.example.designdemo.handler;
import com.example.designdemo.pojo.UserInfo;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 19:26
* @Description:新用户首次购买投放指定业务
*/
public class NewCheckHandler extends AbstractSuggestRequirementHandler{
@Override
public void processHandler(UserInfo userInfo, List<String> suggestLists) {
//通过获取 userinfo 的 buyProducts 属性
boolean newUser = userInfo.isNewUser();
if(newUser) {
suggestLists = new ArrayList<>(); // 特定的新用户奖励
}
}
}
创建PersonnalCheckHandler
代码如下(示例):
package com.example.designdemo.handler;
import com.example.designdemo.pojo.UserInfo;
import java.util.List;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 19:26
* @Description:用户资质是否满足业务投放资质
*/
public class PersonnalCheckHandler extends AbstractSuggestRequirementHandler{
@Override
public void processHandler(UserInfo userInfo, List<String> suggestLists) {
// 通过个人资质的check,我们找到了 4 个可以投放的业务。放到 suggestLists 中。
suggestLists.add("1");
suggestLists.add("2");
suggestLists.add("3");
suggestLists.add("4");
}
}
创建RecentCheckHandler
代码如下(示例):
package com.example.designdemo.handler;
import com.example.designdemo.pojo.UserInfo;
import java.util.List;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 19:26
* @Description:用户近期购买的商品是否符合投放的人群
*/
public class RecentCheckHandler extends AbstractSuggestRequirementHandler{
@Override
public void processHandler(UserInfo userInfo, List<String> suggestLists) {
//通过获取 userinfo 的 buyProducts 属性
List<String> buyProducts = userInfo.getBuyProducts();
// buyProducts 和 之前保留的 3 个 业务信息进行对比。然后筛选出剩余的 2 个 业务投放
suggestLists.remove("2");
}
}
创建SuggestRequirementHandlerProcess
代码如下(示例):
package com.example.designdemo.handler;
import com.example.designdemo.pojo.UserInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 19:26
* @Description:
*/
@Component
public class SuggestRequirementHandlerProcess {
@Value("#{'${suggest.requirement.handler}'.split(',')}")
private List<String> handlers;
public void process(UserInfo userInfo, List<String> suggestLists) {
// 如果想要实时的进行顺序的调整或者是增减。那必须要使用配置中心进行配置。比如springcloud里边自带的 git 的这种配置中心; applo 配置中心;nacos配置中心。
try {
for(String handler : handlers) {
AbstractSuggestRequirementHandler handle =
(AbstractSuggestRequirementHandler) Class.forName(handler).newInstance();
handle.processHandler(userInfo, suggestLists);
}
} catch (Exception e) {
}
}
}
创建UserInfo
代码如下(示例):
package com.example.designdemo.pojo;
import java.util.List;
public class UserInfo {
private String username;
private String city;
private List<String> buyProducts;
private boolean isNewUser;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public List<String> getBuyProducts() {
return buyProducts;
}
public void setBuyProducts(List<String> buyProducts) {
this.buyProducts = buyProducts;
}
public boolean isNewUser() {
return isNewUser;
}
public void setNewUser(boolean newUser) {
isNewUser = newUser;
}
}
创建UserService
代码如下(示例):
package com.example.designdemo.service;
import java.util.List;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:28
* @Description:
*/
public interface UserService {
List<String> suggestRequirement(String username);
}
创建UserServiceImpl
代码如下(示例):
package com.example.designdemo.service.impl;
import com.example.designdemo.handler.SuggestRequirementHandlerProcess;
import com.example.designdemo.pojo.UserInfo;
import com.example.designdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private SuggestRequirementHandlerProcess suggestRequirementHandlerProcess;
@Override
public List<String> suggestRequirement(String username) {
//获取用户信息。因为用户已经登录了,那么user的信息是保存在我们的缓存里的。
UserInfo userInfo = getUserInfo(username);
List<String> results = new ArrayList<>();
//可以发现,调用方无需关心任何 handler。完全对其屏蔽的。而且是完全解耦
suggestRequirementHandlerProcess.process(userInfo, results);
return results;
}
//因为这部分是需要查询 缓存(如果缓存没有,需要查库)不应该写到 service层,但是为了代码书写简便
//这部分我模拟在service 层。
private UserInfo getUserInfo(String username) {
return new UserInfo();
}
}
修改application.properties
代码如下(示例):
# 应用名称
spring.application.name=design-demo
# 这里比喻成配置中心 先后顺序决定投放执行的逻辑
# 这里我们先执行PersonnalCheckHandler用户资质是否满足业务投放资质,为用户添加投放业务1,2,3,4.
# 然后再执行CityCheckHandler用户所在城市是否满足业务投放城市,移除用户投放业务1.
# 接着执行RecentCheckHandler用户近期购买的商品是否符合投放的人群,移除用户投放业务2。
# 最后执行NewCheckHandler新用户首次购买投放指定业务,给业务特定业务奖励。最终给用户投放业务3,4
suggest.requirement.handler=com.example.designdemo.handler.PersonnalCheckHandler,com.example.designdemo.handler.CityCheckHandler,com.example.designdemo.handler.RecentCheckHandler,com.example.designdemo.handler.NewCheckHandler
接口调用测试是否正常工作
如下图(示例):
接口调用逻辑讲解
请求进来
如下图(示例):