策略模式
1.基础知识:
定义∶
定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。
可以干掉if...else...
适用场景
系统有很多类,而他们的区别仅仅在于他们的行为不同
一个系统需要动态地在几种算法中选择一种
比如支付方式的选择
优点
开闭原则
避免使用多重条件转移语句
提高算法的保密性和安全性
缺点
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
产生很多策略类
2.实战
创建学习策略接口
/**
* 学习策略
* @Author LYS
* @Date 2022/1/16 9:25
* @Version 1.0
*/
public interface LearnStrategy {
void doStudy();
}
创建不同的学习实现类
/**
* 语文学习策略
* @Author LYS
* @Date 2022/1/16 9:27
* @Version 1.0
*/
public class ChineseLearnStrategy implements LearnStrategy{
@Override
public void doStudy() {
System.out.println("语文学习策略");
}
}
/**
* 空学习策略
* @Author LYS
* @Date 2022/1/16 9:28
* @Version 1.0
*/
public class EmptyLearnStrategy implements LearnStrategy{
@Override
public void doStudy() {
System.out.println("空学习策略");
}
}
/**
* 英语学习策略
* @Author LYS
* @Date 2022/1/16 9:27
* @Version 1.0
*/
public class EnglishLearnStrategy implements LearnStrategy{
@Override
public void doStudy() {
System.out.println("英语学习策略");
}
}
/**
* 数学学习策略
* @Author LYS
* @Date 2022/1/16 9:26
* @Version 1.0
*/
public class MathLearnStrategy implements LearnStrategy{
@Override
public void doStudy() {
System.out.println("数学学习策略");
}
}
/**
* 执行策略
* @Author LYS
* @Date 2022/1/16 9:33
* @Version 1.0
*/
public class LearnActivity {
private LearnStrategy learnStrategy;
public LearnActivity(LearnStrategy learnStrategy) {
this.learnStrategy = learnStrategy;
}
public void executeLearnStrategy(){
learnStrategy.doStudy();
}
}
测试类
public class Test {
public static void main(String[] args) {
LearnActivity learnActivity = null;
String key = "ENGLISH";
if("ENGLISH".equals(key)){
learnActivity = new LearnActivity(new EnglishLearnStrategy());
}else if("MATH".equals(key)){
learnActivity = new LearnActivity(new MathLearnStrategy());
}else if("CHINESE".equals(key)){
learnActivity = new LearnActivity(new ChineseLearnStrategy());
}else{
learnActivity = new LearnActivity(new EmptyLearnStrategy());
}
learnActivity.executeLearnStrategy();
}
控制台输出
但是这样的代码编写,还是有ifelse,感觉并没有什么软用,只是比原来逻辑清晰了一点,相当于独立抽离代码块,接下来结合工厂模式和单例模式,打出一套必杀组合拳去掉ifelse。
创建工厂
package DesignPattern.strategy;
import java.util.HashMap;
import java.util.Map;
/**
* @Author LYS
* @Date 2022/1/16 9:29
* @Version 1.0
*/
public class LearnStrategyFactory {
private static Map<String, LearnStrategy> LEARN_STRATEGY_MAP = new HashMap<String, LearnStrategy>();
//类加载的时候就执行了静态代码片,类似饿汉模式,空间换时间 使不同的策略是单例的
static {
LEARN_STRATEGY_MAP.put(LearnKey.MATH, new MathLearnStrategy());
LEARN_STRATEGY_MAP.put(LearnKey.CHINESE, new ChineseLearnStrategy());
LEARN_STRATEGY_MAP.put(LearnKey.ENGLISH, new EnglishLearnStrategy());
}
private static final LearnStrategy NON_PROMOTION = new EmptyLearnStrategy();
private LearnStrategyFactory() {
}
public static LearnStrategy getPromotionStrategy(String promotionKey) {
LearnStrategy promotionStrategy = LEARN_STRATEGY_MAP.get(promotionKey);
return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
}
private interface LearnKey {
String MATH = "MATH";
String CHINESE = "CHINESE";
String ENGLISH = "ENGLISH";
}
}
测试类
public static void main(String[] args) {
// String learnKey = "ENGLISH";
// String learnKey = "CHINESE";
String learnKey = "MATH";
LearnActivity promotionActivity = new LearnActivity(LearnStrategyFactory.getPromotionStrategy(learnKey));
promotionActivity.executeLearnStrategy();
}
执行结果:
一行代码搞定所有,简介明了,又使用了单例,相比原来一个执行一个策略就new bean的情况,节省了大量空间,简直是艺术!
3.源码调用:
观察AbstractAutowireCapableBeanFactory类代码,其使用了懒汉式的方法加载策略,这里是用的时cglib动态代理的加载策略
也就是使用单例+策略模式
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/** Strategy for creating bean instances. */
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
/**
* Set the instantiation strategy to use for creating bean instances.
* Default is CglibSubclassingInstantiationStrategy.
* @see CglibSubclassingInstantiationStrategy
*/
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
resource接口策略的抽象
不同的接口就是对不同策略的实现,比如classpathresource
comparator.compare比较器,就是对不同的情况有不同策略的实现
bean的初始化也使用饿了