一、实现思路
-
模板方法:固定推荐流程
-
策略模式:听阈规则 / 价格规则可替换
二、整体设计结构
bash
AbstractProductRecommendTemplate
↓
filterByThreshold() ← 策略①
↓
groupByBrand()
↓
selectByPriceLevel() ← 策略②
↓
buildResult()
三、第一步:定义"推荐模板"(流程写死)
java
public abstract class AbstractProductRecommendTemplate {
public final List<Product> recommend(List<Product> products, UserProfile user) {
// 1、 听阈过滤(最关键)
List<Product> available = filterByThreshold(products, user);
if (available.isEmpty()) {
return Collections.emptyList();
}
// 2、 按品牌分组
Map<String, List<Product>> brandMap = groupByBrand(available);
// 3、 每个品牌选高 / 中 / 低 3种价格的产品,对应不同价格需求的用户群体
return selectByPriceLevel(brandMap, user);
}
protected abstract List<Product> filterByThreshold(
List<Product> products, UserProfile user);
protected Map<String, List<Product>> groupByBrand(List<Product> products) {
return products.stream()
.collect(Collectors.groupingBy(Product::getBrand));
}
protected abstract List<Product> selectByPriceLevel(
Map<String, List<Product>> brandMap, UserProfile user);
}
四、第二步:听阈匹配策略
1、 策略接口
java
public interface ThresholdMatchStrategy {
boolean match(Product product, UserProfile user);
}
2、实现类
java
@Component("DEFAULT_THRESHOLD")
public class DefaultThresholdStrategy implements ThresholdMatchStrategy {
@Override
public boolean match(Product p, UserProfile user) {
return p.getMinHz() <= user.getMinHz()
&& p.getMaxHz() >= user.getMaxHz();
}
}
五、第三步:价格选择策略
1、 策略接口
java
public interface PriceSelectStrategy {
List<Product> select(List<Product> products);
}
2、 高 / 中 / 低 价格策略
java
@Component("HIGH_MID_LOW")
public class HighMidLowPriceStrategy implements PriceSelectStrategy {
@Override
public List<Product> select(List<Product> products) {
if (products.size() <= 3) {
return products;
}
products.sort(Comparator.comparing(Product::getPrice));
Product low = products.get(0);
Product mid = products.get(products.size() / 2);
Product high = products.get(products.size() - 1);
return List.of(low, mid, high);
}
}
六、模板的实现类组合使用上面的2个策略
java
@Autowired
private ThresholdMatchStrategy thresholdStrategy;
@Autowired
private PriceSelectStrategy priceSelectStrategy;
@Override
protected List<Product> filterByThreshold(List<Product> products, UserProfile user) {
return products.stream()
.filter(p -> thresholdStrategy.match(p, user))
.collect(Collectors.toList());
}
@Override
protected List<Product> selectByPriceLevel(
Map<String, List<Product>> brandMap, UserProfile user) {
List<Product> result = new ArrayList<>();
brandMap.forEach((brand, list) -> {
result.addAll(priceSelectStrategy.select(list));
});
return result;
}
七、Controller / Service 使用方式
java
@Autowired
private ProductRecommendService recommendService;
public List<Product> recommend(Long userId) {
UserProfile user = userService.getProfile(userId);
List<Product> products = productRepository.findAll();
return recommendService.recommend(products, user);
}
这套设计特别适用于以下场景:
-
听力产品推荐
-
活动商品推荐
-
套餐组合
-
分档定价