
前言
公司早期开发的项目,接手后需要根据不同的data source 进行迭代优化。data source数据源非常多,不同的数据源需要根据不用的产品规则进行处理。因此,老代码的里大量的if else判断非常多······。说实话刚开始不太敢动手改,非常头疼。但是经过一番思考过后,毅然决定进行重构。所谓长痛不如短痛······
而消除if else 有很多方法,网上目前很多类似的例子。大多都比较抽象,实际的应用过程中,就需要自己独立思考,实现适合当前项目的最佳方式。笔者一开始也遇到了不少麻烦。下面本文通过结合Flink中常用的map算子,实现策略模式+工厂模式的应用。
定义
首先说明下该设计模式的定义,策略模式是指有一组算法,它将每个算法都封装起来,并且可使它们之间可以相互替换,在客户端调用它们时可以互不影响。
这里需要理解三个角色
- 抽象策略
- 具体策略
- 上下文环境
- 抽象策略是接口或者抽象类的封装,一般来定义一个方法,可以写成函数式接口,满足单一职责的原则。
- 具体策略是用于实现抽象策略的子类或实现类。是消除复杂if判断的关键,不同的策略实现类承接不同的业务方法和逻辑。
- 上下文环境可以理解为对抽象策略的使用,客户端调用上下文环境
UML

上面的UML类图举了一个导航的例子,到达目的地有多种策略,公共交通、自驾、步行都是抽象策略的具体实例。而我们手机里的导航,就是上下文环境。客户端就是用户,用户通过导航来实现策略的使用。
此处省略示例代码
实战应用
下面是项目实际中使用的代码。去除了业务相关的属性,减少了策略实现类的数量,旨在说明问题。
首先定义抽象策略接口:
1 2 3
| public interface IBaseStrategy { List<OutputEntity> doCleanFieldAlg(InputEntity s); }
|
其次 定义具体策略类,实现该抽象策略接口,具体的策略里包含对业务的封装
1 2 3
| public class LocalAllCreditChinaFieldClean implements IBaseFieldCleanStrategy { }
|
然后,定义上下文的引用
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class BaseContext {
public List<OutpuEntity> doClean(InputEntity sp) { if (CollectionUtils.isNotEmpty(sp.getCustomsHeadquarters())) { return BaseFactory.getType(MyType.HGZS.getValue()).doCleanFieldAlg(sp); }
if (CollectionUtils.isNotEmpty(sp.getFinancePunishEntities())) { return BaseFactory.getType(MyType.YH.getValue()).doCleanFieldAlg(sp); } return Collections.emptyList(); } }
|
然后,抽象工厂初始化策略类到map里
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class BaseFactory { private static Map<String, IBaseStrategy> strategyMap = new HashMap<>();
static { strategyMap.put(PunishType.HGJCK.getValue(), new SourceHandlerV1()); strategyMap.put(PunishType.HGZS.getValue(), new SourceHandlerV2()); strategyMap.put(PunishType.YH.getValue(), new SourceHandlerV3()); strategyMap.put(PunishType.SJJXYZG.getValue(), new SourceHandlerV4()); }
public static IBaseStrategy getType(String type) { return strategyMap.get(type); } }
|
枚举类封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public enum MyType { HGJCK(1,"source1"), HGZS(2,"source2"), YH(3,"source3"), SJXYZG(4,"source4") ;
private int code; private String value;
PunishType(int code, String value) { this.code = code; this.value = value; }
public int getCode() { return code; }
public String getValue() { return value; } }
|
最后,在入口的FlatMap中,直接创建上下文类来调用策略方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class ProcessingFlatMap implements FlatMapFunction<InputEntity, OutputEntity> { @Override public void flatMap(InputEntity sp, Collector<OutputEntity> out) { if (sp != null) { List<OutputEntity> list = new BaseContext().doClean(sp); if (CollectionUtils.isNotEmpty(list)) { list.forEach(e -> { if (e != null) { out.collect(e); } }); } } } }
|
总结
Copyright Notice: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!