【设计模式】 | 策略模式源码学习与实践
前言
在业务开发中,我们最经常使用到的判断就是if...else,只要涉及到多种策略的实现方式,我们脑海中就会使用这个判断。有时候产品需求的不明确,一个版本迭代来一种判断,随着时间的推移,这个实现方法就会变得又长又臭,那有什么办法可以来觉得呢,通过学习策略模式,他能够很好的帮我们解决这个问题。
纲要
在学习之前,有一句话我觉得比设计模式更重要。
设计原则和思想比设计模式更加普适和重要
什么是策略模式?
简单的来说,就是定义一系列算法,封装每个算法,并使它们可以互换。
策略让算法独立于使用它的客户端而变化。
1. 三个关键角色
三个关键角色
2. 目的
实现不同的策略,将策略分离
3. 为什么要使用策略模式
主要有三个原因
为什么使用策略模式?
优缺点
优缺点
场景分析
通过第一部分,我们对策略模式有了一个大概的认识,那他主要针对于什么场景呢
- 需要动态切换不同算法
- 多重的条件选择业务场景
- 客户端只关心调用,不关心算法细节
- 分离策略
源码案例
源码案例
我们可以通过优秀的代码中学习策略模式的实现
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<Method> currentlyInvokedFactoryMethod = 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());
}
}
这就是一个策略模式的实现,可以看出代码量一下就上去了,如果在规则简单而且情况少的情况下,我们可能就不需要再去使用策略模式,因为它不够直观。
转载自:https://juejin.cn/post/7035602073743785998