【设计模式】 | 策略模式源码学习与实践

3,583 阅读3分钟

前言

在业务开发中,我们最经常使用到的判断就是if...else,只要涉及到多种策略的实现方式,我们脑海中就会使用这个判断。有时候产品需求的不明确,一个版本迭代来一种判断,随着时间的推移,这个实现方法就会变得又长又臭,那有什么办法可以来觉得呢,通过学习策略模式,他能够很好的帮我们解决这个问题。

纲要

在学习之前,有一句话我觉得比设计模式更重要。

设计原则和思想比设计模式更加普适和重要

策略模式

什么是策略模式?

简单的来说,就是定义一系列算法,封装每个算法,并使它们可以互换。

策略让算法独立于使用它的客户端而变化。

1. 三个关键角色

三个关键角色

三个关键角色

2. 目的

​ 实现不同的策略,将策略分离

3. 为什么要使用策略模式

​ 主要有三个原因

为什么使用策略模式?

为什么使用策略模式?

优缺点

优缺点

优缺点

场景分析

通过第一部分,我们对策略模式有了一个大概的认识,那他主要针对于什么场景呢

  1. 需要动态切换不同算法
  2. 多重的条件选择业务场景
  3. 客户端只关心调用,不关心算法细节
  4. 分离策略

源码案例

源码案例

源码案例

我们可以通过优秀的代码中学习策略模式的实现

SimpleInstantiationStrategy中分析出它的关键角色

可以从命名中看出,SimpleInstantiationStrategy是其中的某一个策略,我们在写策略模式的时候最好也以Strategy为结尾,表名这就是个策略。

1.抽象策略类

public interface InstantiationStrategy {
    Object instantiate(RootBeanDefinition var1, @Nullable String var2, BeanFactory var3) throws BeansException;

    Object instantiate(RootBeanDefinition var1, @Nullable String var2, BeanFactory var3, Constructor<?> var4, Object... var5) throws BeansException;

    Object instantiate(RootBeanDefinition var1, @Nullable String var2, BeanFactory var3, @Nullable Object var4, Method var5, Object... var6) throws BeansException;
}

2.具体策略类

public class SimpleInstantiationStrategy implements InstantiationStrategy {
    private static final ThreadLocal<MethodcurrentlyInvokedFactoryMethod = new ThreadLocal();

    public SimpleInstantiationStrategy() {
    }

    @Nullable
    public static Method getCurrentlyInvokedFactoryMethod() {
        return (Method)currentlyInvokedFactoryMethod.get();
    }

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
       //...
    }

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, Constructor<?> ctor, Object... args) {
      //...
    }

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Object factoryBean, Method factoryMethod, Object... args) {
      //...
}

3.上下文信息类

这里没有找到上下文信息类,我们可以理解为上下文就是来存取策略的一个地方。在这里可以与工厂模式有一个很好的结合,在实践demo中给大家展示。

实践

与工厂模式结合:

上下文信息类:

@Component
public class rulesFactory {
    private static final Map<Integer,RuleStrategy> map = new HashMap<>(20);

    @Resource
    public selectStrategy selectStrategy;

    //@PostConstruct 用来修饰一个非静态的void()方法.而且这个方法不能有抛出异常声明。在服务器加载Servlet的时候运行,并且只会被服务器调用一次
    @PostConstruct
    public void init(){
        map.put(1,selectStrategy);
    }

    public RuleStrategy creator(Integer type) {
        return map.get(type);
    }
}

抽象策略(Strategy)角色:

public interface RuleStrategy<T extends RulesProcessorBO> {
    
    void process(T t);
}

环境角色(组件,直接调用工厂):

@Component
public class RuleContext {

    @Resource
    private rulesFactory bizRuleFactory;

    public void process(RulesProcessorBO rulesProcessorBO) {

        bizRuleFactory.creator(rulesProcessorBO.getRuleCode()).process(rulesProcessorBO);

    }

}

具体策略(ConcreteStrategy)角色:

@Component
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class selectStrategy implements RuleStrategy<selectProcessorBo> {

    @Autowired
    private ManagerMapper managerMapper;

    @Override
    public void process(selectProcessorBo rulesProcessorBO) {
        Manager m = managerMapper.getById("1");
        System.out.println(m.toString());

    }
}

这就是一个策略模式的实现,可以看出代码量一下就上去了,如果在规则简单而且情况少的情况下,我们可能就不需要再去使用策略模式,因为它不够直观。