4.策略模式

268 阅读3分钟

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.第五步

输出:星期二拳击