在《vivo 营销自动化技术解密 |开篇》中,我们从整体上介绍了vivo营销自动化平台的业务架构、核心业务模块功能、系统架构和几大核心技术设计。
本次带来的是系列文章的第2篇,本文详细解析设计模式和相关应用如何帮助营销自动化业务提升系统扩展性,以及实践过程中的思考和总结。
一、引言
营销业务本身极具复杂多变性,特别是伴随着数字化营销蓬勃发展的趋势,在市场的不同时期、公司发展的不同阶段、面向不同的用户群体以及持续效果波动迭代,都会产生不同的营销策略决策。
当面对随时变化的业务场景时,系统的扩展性就显得非常重要。而在谈到系统设计扩展性的时候,总是首先会想到设计原则和设计模式。但设计模式不是银弹,并不能解决所有问题,它只是前人提炼总结出来的招式方法,需要开发者根据实际业务场景进行合理的选择、合适的变通,才能真正去解决实际场景中的问题,并总结形成自己的方法论。
那么接下来我们看看设计模式是如何帮助我们在营销策略引擎中提升系统扩展性的。
二、营销策略引擎
先简单介绍一下营销策略引擎:策略引擎是通过搭建可视化流程组件,定义各个流程节点,自动化执行活动业务流程,从而提供不同运营活动能力。其中核心活动业务流程主要包括三大部分:运营活动配置->运营活动审批->运营活动执行。
- 运营活动配置:运营人员在系统后台配置运营活动。包括活动名称、活动时间、触发条件、活动用户和具体推送渠道(如短信、微信、push推送等)。
- 运营活动审批:品质/主管人员审批运营活动配置。审批流程涉及了活动审批节点和人员的配置,审批相关的回调操作配置。
- 运营活动执行:系统自动化执行运营活动的过程。即具体的渠道如短信、微信、push等推送活动的任务执行下发流程,包括用户数据准备,数据下发推送和数据效果回收等。
三、设计模式具体应用
3.1 运营活动配置
3.1.1 工厂模式
具体场景
一般情况下,根据不同的用户和活动场景,运营借助数据分析会决策出不同的活动策略,比如需要创建短信推送策略、微信图文推送策略、App Push推送策略等。此时我们可以使用工厂模式,统一管理具体推送策略的创建。
模式分析
在GoF《设计模式:可复用面向对象软件的基础》中:工厂模式被分成了工厂方法和抽象工厂两类,而简单工厂模式(又称静态工厂模式)被看作是工厂方法的一种特例。不过由于简单工厂和工厂方法相对更简单和易于理解,代码可读性也更强,因此在实际项目中更加常用。
其中简单工厂的适用场景:
a.工厂类负责创建的对象比较少,工厂方法中的创建逻辑简单。
b.客户端无须关心创建具体对象的细节,仅需知道传入工厂类的类型参数。
而工厂方法的适用场景:
a.工厂类对象创建逻辑相对复杂,需要将工厂实例化延迟到其具体工厂子类中。
b.适合需求变更频繁的场景,可以利用不同的工厂实现类支持新的工厂创建方案,更符合开闭原则,扩展性更好。
典型代码示例
//抽象产品类 public abstract class Product { public abstract void method(); } //具体的产品类 class ProductA extends Product { @Override public void method() { //具体的执行逻辑 } } //抽象工厂模板类 abstract class Factory<T> { abstract Product createProduct(Class<T> c); } //具体工厂实现类 class FactoryA extends Factory{ @Override Product createProduct(Class c) { Product product = (Product) Class.forName(c.getName()).newInstance(); return product; } }
实际代码
/** * @author chenwangrong * 活动策略工厂类 */ @Component @Slf4j public class ActivityStrategyFactory { /** * 获得渠道类型对应的策略 * * @param channelType channelType * @return OperationServiceStrategy */ public static ActivityStrategy getActivityStrategy(ChannelTypeEnum channelType) { ChannelTypeStrategyEnum channelTypeStrategyEnum = ChannelTypeStrategyEnum.getByChannelType(channelType); Assert.notNull(channelTypeStrategyEnum , "指定的渠道类型[channelType=" + channelType + "]不存在"); String strategyName= channelTypeStrategyEnum.getHandlerName(); Assert.notNull(strategyName, "指定的渠道类型[channelType=" + channelType + "未配置策略"); return (ActivityStrategy)SpringContextHolder.getBean(handlerName); } public enum ChannelTypeStrategyEnum { /** * 短信渠道 */ SMS(ChannelTypeEnum.SMS, "smsActivityStrategy"), /** * 微信渠道 */ WX_NEWS(ChannelTypeEnum.WX, "wxActivityStrategy"), /** * push渠道 */ PUSH(ChannelTypeEnum.PUSH, "pushActivityStrategy"),; private final ChannelTypeEnum channelTypeEnum; private final String strategyName; ChannelTypeStrategyEnum (ChannelTypeEnum channelTypeEnum, String strategyName) { this.channelTypeEnum = channelTypeEnum; this.strategyName= strategyName; } public String getStrategyName() { return strategyName; } public static ChannelTypeStrategyEnum getByChannelType(ChannelTypeEnum channelTypeEnum) { for (ChannelTypeStrategyEnum channelTypeStrategyEnum : values()) { if (channelTypeEnum == channelTypeStrategyEnum.channelTypeEnum) { return channelTypeStrategyEnum ; } } return null; } } }
实践总结
在实际项目代码中我们采用的是简单工厂模式(静态工厂模式),实现时利用枚举(或者映射配置表)来保存渠道类型与具体策略实现类的映射关系,再结合Spring的单例模式,来进行策略类的创建。
相比于工厂方法模式,在满足业务的前提下,减少了工厂类数量,代码更加简单适用。