一、实现思路
模板方法:固定推荐流程
策略模式:听阈规则 / 价格规则可替换
二、整体设计结构
AbstractProductRecommendTemplate ↓ filterByThreshold() ← 策略① ↓ groupByBrand() ↓ selectByPriceLevel() ← 策略② ↓ buildResult()三、第一步:定义“推荐模板”(流程写死)
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、 策略接口
public interface ThresholdMatchStrategy { boolean match(Product product, UserProfile user); }2、实现类
@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、 策略接口
public interface PriceSelectStrategy { List<Product> select(List<Product> products); }2、 高 / 中 / 低 价格策略
@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个策略
@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 使用方式
@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); }这套设计特别适用于以下场景:
听力产品推荐
活动商品推荐
套餐组合
分档定价