1.为啥要学习策略模式
1.面试需要
2.代替if-else (通常策略模式+工厂模式 实现)
3.将算法的定义和使用分离 (将每个算法都封装起来,并且使它们之间可以互换。)
2.策略模式简介
策略模式使用的就是面向对象的继承和多态机制
● Context封装角色 (锦囊)
它也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,
封装可能存在的变化。
● Strategy抽象策略角色 (计谋)
策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。各
位看官可能要问了,类图中的AlgorithmInterface是什么意思,嘿嘿,algorithm是“运算法则”的
意思,结合起来意思就明白了吧。
● ConcreteStrategy具体策略角色 (使用者)
实现抽象策略中的操作,该类含有具体的算法
3.优缺点
优点:
1.算法可以自由切换
2.避免使用多重条件判断
3.扩展性良好
缺点:
1.策略类数量增多
2.所有的策略类都需要对外暴露 (需要结合工厂模式,代理模式结合)
4.使用场景
动态切换算法,代替if else
5.案例
需求:学生日常安排,周末到工作日,并输出
可以对比:责任链模式
juejin.cn/post/699580… juejin.cn/post/699580…
版本1:最low的版本
1.策略角色 (计谋)
public interface 计谋{
String 活动(String week);
}
2.Context封装角色(锦囊) 锦囊里面放计谋
public class 锦囊 {
private 计谋 jm = null;
public 锦囊(计谋 jm) {
this.jm = jm;
}
public String 活动(String week) {
return this.jm.活动(week);
}
}
3.具体的计谋方法
计谋1: 打飞机
public class 打球 implements 计谋{
@Override
public String 活动(String week) {
return "星期三打球";
}
}
计谋2: 拳击
public class 拳击 implements 计谋{
@Override
public String 活动(String week) {
return "星期二拳击";
}
}
计谋3: 跳舞
public class 跳舞 implements 计谋{
@Override
public String 活动(String week) {
return "星期一跳舞";
}
}
4.拿到精囊并使用
public class 使用者吴签 {
public static void main(String[] args) {
//上下文
锦囊 context = null;
String week = "星期二";
if ("星期一".equals(week)) {
context = new 锦囊(new 跳舞());
} else if ("星期二".equals(week)) {
context = new 锦囊(new 拳击());
} else if ("星期三".equals(week)) {
context = new 锦囊(new 打球());
}
System.out.println(context.活动(week));
}
}
5.问题:
1.还是会使用到if else
2.打大量的妙计 暴露客户端
版本: 策略模式+工厂模式 (吴签只关心结果,不关心的那些妙计)
根据传入的参数,获取工厂对应对象
1.第一步
import org.springframework.beans.factory.InitializingBean;
public interface 计谋 extends InitializingBean {
String 活动(String week);
}
2.第二步
public class Factory {
private static Map<String, 计谋> strategy计谋Map = new HashMap<>();
/**
* 根据name获取对应的handler实现
* @param name
* @return
*/
public static 计谋 getInvokeStrategyMap计谋(String name){
return strategy计谋Map.get(name);
}
/**
* 注册 启动项目的时候 就会注册到 spring中
* @param name
* @param handler
*/
public static void register计谋(String name, 计谋 handler){
if(StringUtils.isEmpty(name)||null == handler){
return;
}
strategy计谋Map.put(name,handler);
}
}
3.第三步
@Component
public class 打球 implements 计谋{
@Override
public String 活动() {
return "星期三打球";
}
@Override
public void afterPropertiesSet() throws Exception {
Factory.register计谋("星期三",this);
}
}
@Component
public class 拳击 implements 计谋{
@Override
public String 活动() {
return "星期二拳击";
}
@Override
public void afterPropertiesSet() throws Exception {
Factory.register计谋("星期二",this);
}
}
@Component
public class 跳舞 implements 计谋{
@Override
public String 活动() {
return "星期一跳舞";
}
@Override
public void afterPropertiesSet() throws Exception {
Factory.register计谋("星期一",this);
}
}
4.第四步
计谋 jm= Factory.getInvokeStrategyMap计谋("星期二");
System.out.println(jm.活动());
5.第五步
输出:星期二拳击