使用模板模式+策略模式实现产品推荐

一、实现思路

  • 模板方法:固定推荐流程

  • 策略模式:听阈规则 / 价格规则可替换

二、整体设计结构

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);
}

这套设计特别适用于以下场景:

  • 听力产品推荐

  • 活动商品推荐

  • 套餐组合

  • 分档定价

相关推荐
侠客行03173 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪3 小时前
深入浅出LangChain4J
java·langchain·llm
老毛肚4 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
风流倜傥唐伯虎5 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
Yvonne爱编码5 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚5 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言
你这个代码我看不懂5 小时前
@ConditionalOnProperty不直接使用松绑定规则
java·开发语言
fuquxiaoguang5 小时前
深入浅出:使用MDC构建SpringBoot全链路请求追踪系统
java·spring boot·后端·调用链分析
琹箐5 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
__WanG5 小时前
JavaTuples 库分析
java