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

一、实现思路

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

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

二、整体设计结构

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

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

  • 听力产品推荐

  • 活动商品推荐

  • 套餐组合

  • 分档定价

相关推荐
华仔啊5 分钟前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing26 分钟前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
日月云棠16 小时前
各版本JDK对比:JDK 25 特性详解
java
用户83071968408217 小时前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide17 小时前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家18 小时前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java
花花无缺18 小时前
搞懂new 关键字(构造函数)和 .builder() 模式(建造者模式)创建对象
java
用户9083246027318 小时前
Spring Boot + MyBatis-Plus 多租户实战:从数据隔离到权限控制的完整方案
java·后端
桦说编程19 小时前
实战分析 ConcurrentHashMap.computeIfAbsent 的锁冲突问题
java·后端·性能优化
程序员清风1 天前
用了三年AI,我总结出高效使用AI的3个习惯!
java·后端·面试