一、什么是策略模式

策略模式属于行为型设计模式。定义了一系列算法,并将这些算法封装到一个类中,使得他们可以相互替换。这样,我们可以在改变某个对象使用的算法的情况下,选择一个合适的算法来处理特定的任务,主要解决多重if-else的判断逻辑。

二、角色组成

  • 环境类(Context):环境类是策略模式的核心类,它持有一个策略对象的引用,并在需要时调用策略对象的方法。
  • 抽象策略类(Strategy):定义了策略方法,这些方法表示不同的策略行为。
  • 具体策略类(Concrete Strategy):抽象策略类的实现,它实现了抽象策略类中定义的策略方法,并提供了具体的算法实现。不同的具体策略类具有不同的实现算法,它们之间可以相互替换,使得环境类在运行时可以动态地改变策略。

三、优缺点 

优点:

  • 算法可以自由切换。
  • 避免使用多重条件判断。
  • 扩展性良好

缺点:

  • 策略类会增多。
  • 所有策略类都需要对外暴露。
  • 判断逻辑在客户端,需求改变时,要更改客户端的程序。

四、应用场景

4.1 生活场景

  • 手机开锁方式:密码、指纹、面部识别
  • 出游的交通方式:自驾、汽车、火车、飞机、高铁,每一种方式都是一个策略。
  • 开通csdn会员的方式:月卡、年卡、超级年卡、两年卡、连续包月。

4.2 java场景

  • Spring Security中的认证和授权策略:在Spring Security中,可以使用不同的策略来定义认证和授权的行为,例如PasswordAuthentication(密码验证)、RememberMeAuthentication(记住我功能验证)、RoleBasedAuthorization(基于角色的授权)等。通过配置不同的策略,可以灵活地适应不同的安全需求。
  • Comparator接口:在使用排序算法时,可以通过实现Comparator接口来定义不同的比较策略,从而可以根据需求对对象进行自定义排序。
  • 线程池(ThreadPoolExecutor):在ThreadPoolExecutor中,可以通过设定不同的拒绝策略(RejectedExecutionHandler)来处理无法提交的新任务。拒绝策略可以根据系统的需求选择不同的处理方式,如抛出异常、丢弃任务等。

五、代码实现

下面以视频平台为例,解释一下策略模式。

  • 环境类(Context):VideoContext
  • 抽象策略类(Strategy):VideoStrategy
  • 具体策略类(Concrete Strategy):DyVideoStrategy、WxVideoStrategy、KsVideoStrategy

5.0、UML类图

5.1、VideoContext——环境类(Context)

/**
 * @author Created by njy on 2023/5/25
 * 1.策略环境类(Context)
 * 在初始化VideoContext对象时,将所有策略实现类塞进Map中,
 * key为视频类型(dy、ks、wx) value为对应的视频实现类
 * 通过getVideoStrategy方法,根据videoType从map中渠道对应的视频策略
 * 从而隐藏了策略的具体实现逻辑。这种方式可以遵循开闭原则,因为在新增视频类型时,只需要增加对应的实现类
 */
@Component
public class VideoContext {

    private static final Map<String, VideoStrategy> videoMap = new HashMap<>();

    /**
     * 对象初始化时,将所有策略实现类加入到map中
     * @param videoStrategies
     */
    public VideoContext(List<VideoStrategy> videoStrategies) {
        videoStrategies.forEach(strategy -> videoMap.put(strategy.getVideoType(), strategy));
    }

    /**
     * 根据videoType获取对应的策略实现类
     * @param videoType
     * @return
     */
    public VideoStrategy getVideoStrategy(String videoType){
        VideoStrategy videoStrategy = videoMap.get(videoType);
        if (videoStrategy==null) {
            throw new RuntimeException("videoType inValid!");
        }
        return videoStrategy;
    }
}

5.2、VideoStrategy——抽象策略类(Strategy)

/**
 * @author Created by njy on 2023/5/25
 * 2.抽象策略类(Strategy)
 */
public interface VideoStrategy {
    //刷视频
    String brushVideo();
    //视频类型
    String getVideoType();
}

5.3、具体策略类(Concrete Strategy)

/**
 * @author Created by njy on 2023/5/25
 *  3.具体策略类(Concrete Strategy):微信
 */
@Component
public class WxVideoStrategy implements VideoStrategy{
    @Override
    public String brushVideo() {
        return "我在刷微信视频号";
    }

    @Override
    public String getVideoType() {
        return "wx";
    }
}
/**
 * @author Created by njy on 2023/5/25
 *  3.具体策略类(Concrete Strategy):快手
 */
@Component
public class KsVideoStrategy implements VideoStrategy{
    @Override
    public String brushVideo() {
        return "我在刷快手";
    }

    @Override
    public String getVideoType() {
        return "ks";
    }
}
/**
 * @author Created by njy on 2023/5/25
 * 3.具体策略类(Concrete Strategy):抖音
 */
@Component
public class DyVideoStrategy implements VideoStrategy{
    @Override
    public String brushVideo() {
        return "我在刷抖音";
    }

    @Override
    public String getVideoType() {
        return "dy";
    }
}

5.4、TestStrategy

/**
 * @author njy
 * @date 2023/5/24 13:58
 * 策略模式测试类
 */
@SpringBootTest
public class TestStrategy {

    @Autowired
    private VideoContext videoContext;

    @Test
    void testStrategy(){
        //策略模式
        VideoStrategy video1 = videoContext.getVideoStrategy("dy");
        String v1 = video1.brushVideo();
        System.out.println("v1 : " + v1);
        VideoStrategy video2 = videoContext.getVideoStrategy("ks");
        String v2 = video2.brushVideo();
        System.out.println("v2 : " + v2);
        VideoStrategy video3 = videoContext.getVideoStrategy("wx");
        String v3 = video3.brushVideo();
        System.out.println("v3 : " + v3);

    }
}

END:更多设计模式的介绍,推荐移步至👉 23种设计模式学习导航(Java完整版)👈

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐