谈谈组合策略模式及在生产的应用
组合模式
学设计模式第一次听到这个模式时被迷惑了,以为所谓的组合模式是跟面向对象编程里的组合概念的一样
// 想象中的组合模式
class Car {
private Door door;
private Wheel Whee;
}
读了 GOF 的设计模式之后,书里是将组合模式描述为
将对象组合成树形结构的部分-整体层次结构,使得客户使用单个对象或组合对象都有一致性
也就是说组合部分与被组合部分在对外表现上,应该都是一致的,也就是其实是这样的
class Node {
private Node part1;
private Node part2;
}
真正让我理解组合模式和它的妙用是在《领域驱动设计》这本书里面,作者提出了一个航线的概念,也就是这样,通过组合基本组件以达到功能更强大的一个组件
interface Route {
Route segement1, segement2;
} // 路线
class NationalHighway implements Route{} // 国道
class CountryRoad implements Route {} // 乡道
策略模式
所谓策略,则可以理解为针对某种特定问题的算法,由于不同的算法各有优劣,所以需要将策略抽象为一个接口,让客户代码根据需求选择不同策略来解决问题,代码如下
interface Strategy{
void execute(..);
}
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
void execute(){
strategy.execute(..);
}
}
class StrategyA implements Strategy{
// 具体实现
}
// 使用
Context context = new Context(new StrategyA());
context.execute();
二者的结合
组合与策略两者的结合,不仅可以充分利用组合模式的灵活性,同时也可以利用策略模式的不同算法可选择性
interface Strategy{
void execute(..);
}
class StrategyA implements Strategy{
// 具体实现
}
class StrategyB implements Strategy{
// 具体实现
}
// 组合策略
class CompositeStrategy implements Strategy {
private Strategy strategyA, strategyB;
}
通过组合不仅可以显式编程,交由不同的具体客户满足不同的需求,同时细粒度的策略也暴露了出去,也能让策略更有针对性及可选择性,更进一步,可以使用工厂模式将策略的组装与生成封装在工厂内部,这样客户代码也不必关心他使用的具体策略是什么,只要策略满足他的需求即可
生产上的应用
这个业务场景是这样
- 我们有许多三方接口来获取某种信息
- 每种接口不仅需要单独对外提供服务,同时也需要聚合所有接口数据再对外提供服务
通过封装,这些返回的信息基本上都是一样的,但由于我们的项目在不同的地方运行,不同的地方可能有些接口可用,有些接口不可用,所以此时就通过组合策略模式来满足以上的所有需求
interface FetchInfoStrategy {
Info fetch(...);
}
// 具体三方接口
class ThirdPartAFetchInfoStrategy implements FetchInfoStrategy{...}
class ThirdPartBFetchInfoStrategy implements FetchInfoStrategy{...}
class ThirdPartCFetchInfoStrategy implements FetchInfoStrategy{...}
// 组合三方接口
class CompositeFetchInfoStrtegy implements FetchInfoStrategy {
// 通过配置化动态注入
private static final List<Class<? extends FetchInfoStrategy>> STRATEGY_LIST;
Info fetch(...) {
// 循环调用策略,记录各个接口返回结果
// 合并结果并返回
}
}
通过这样子的组合策略,不仅满足了需求,也为后续的优化留下了空间,若想通过异步调用各个接口,或者调整具体合并逻辑,都可以通过新增一个组合策略,避免修改老代码带来预期之外的问题