浅谈模板方法在推荐系统中的应用
个人仅接触过推荐门户相关的业务逻辑,以下内容均跟实际接触到的业务有关系。
背景:我接触到的大多数推荐业务逻辑大体上分下面几步操作。
#省略前期各种处理
1、具体商品取数逻辑&打标
2、坑位干预
3、前置过滤器处理
4、寻源处理(基本信息,价格)
5、白底图
6、实时分销(黑商家)
7、全局后置过滤器
8、打散&封装商品
#省略前期各种处理
推荐场景基本上都会有以上相关步骤,支持各流程开关控制配置。如:商品详情页猜你喜欢,商品详情页店铺推荐,这两个场景接口推荐的商品取数逻辑是完全不同的,但是基本上都会走坑位,价格基本信息,全局过滤器,黑商家等逻辑。当我们想新增很多推荐场景,如购物车猜你喜欢,购物车常购,大促会场小家电推荐,首页特卖,会员凑单等等场景时,是不是全部都要写一边所有的逻辑?那不是把兄弟们给恶心吐了🤮
基于以上业务特点,如何能最大化的复用逻辑,优化代码结构,增加后期可维护性,此时模板方法出现了(救世主/(ㄒoㄒ)/~~)。
模板方法:一般是为了统一子类的算法实现步骤,或者约束整个流程,所使用的一种手段或者说是方式。它在父类中定义一系列算法的步骤,而将具体的实现都推迟到子类,父类保留部分default实现(非default修饰符的方法,根据情况可以用protected)可供子类选择是否使用(是否覆盖)。最典型的表现就是一个接口,一个抽象父类,父类中会有一系列的抽象方法,而在子类中去逐个实现这些方法。
具体涉及三个类:1、顶层次接口processService(List<T> getResult()),processServcieTemplate implements processService, specifyProcessService(具体每个业务场景的不同取值逻辑)。大体的结构如下:
大体代码结构
顶层processService
@FunctionalInterface public interface PorcessService { /** * 具体的商品获取方法入口 * @param params * @return */ List<Recommend> getResult(RecommendParams params); }
AbstractProcessTemplate
public abstract class AbstractProcessServiceTemplate implements PorcessService { @Override public List<Recommend> getResult(RecommendParams params) { List<Recommend> recommendsList = process(params); /** * 执行具体的推荐步骤 * 1,逻辑取值 * 2,过滤等 * 3... */ return recommendsList; } /** * 子类覆盖具体的取值逻辑 * @param params * @return */ protected abstract List<Recommend> process(RecommendParams params); /** * 价格 * 坑位 * 过滤器等处理函数 */ }
ConcreteProcessServiceImpl
public class ConcreteProcessServiceImpl extends AbstractProcessServiceTemplate{ /** * 子类的取数逻辑 * @param params * @return */ @Override protected List<Recommend> process(RecommendParams params) { return null; } /** * 数据转换方法 * 坑位数据&非坑位数据打标 * 等等 */ }
当有相关业务新增某个场景,如购物车常购,仅需增加子类,处理自己的取值逻辑即可,提高代码的复用性和可维护性。