title: 策略模式
author: rack-leen
avatar: /images/favicon.png
authorDesc: 脱发典范
comments: true
copyright: true
date: 2019-5-19 22:13:05
tags:


策略模式

定义

Define a family of algorithms , encapsulate each one , and make them interchangeable.
定义一组算法,将每个算法封装起来,并且使它们之间可以互换。

策略模式示意图

策略模式

流程

  1. 定义一个总的策略接口,所有的具体策略都要实现这个接口,因为这些策略都有相同的目标。
  2. 将策略封装进策略上下文,让策略有完整的过程。
  3. 客户直接就使用这个完整的过程。

代码实现

策略

  1. 策略总接口
/**
 * 策略总接口
 */
public interface IStrategy {
    /* 对外提供的策略接口 */
    public void strategy();
}
  1. 实现总接口的具体策略1
public class Strategy1 implements IStrategy {
    /* 具体策略1,我们需要的第一个策略 */
    @Override
    public void strategy() {
        System.out.println("策略1");
    }
}
  1. 实现总接口的具体策略2
public class Strategy2 implements IStrategy{
    /* 具体策略2,我们需要的第二个策略 */
    @Override
    public void strategy() {
        System.out.println("策略2");
    }
}
  1. 实现总接口的具体策略3
public class Strategy3 implements IStrategy {
    /* 具体策略3,我们需要的第三个策略 */
    @Override
    public void strategy() {
        System.out.println("策略3");
    }
}

封装

将策略进行封装

/**
 * 策略上下文,封装策略,将需要的策略置于需要的场景中
 */
public class Context {
    private IStrategy strategy ;

    /* 获取封装的策略 */
    public IStrategy getStrategy(){
        return strategy ;
    }

    /* 将需要的策略放入策略上下文中 */
    public void setStrategy(IStrategy strategy){
        this.strategy = strategy ;
    }

    /* 执行策略,可以在策略周围添加我们需要的逻辑 */
    public void executeStrategy(){
        System.out.println("策略开始执行");
        strategy.strategy();
        System.out.println("策略执行完成");
    }
}

场景实现

public class Test{
    public static void main(String[] args) {
        /* 先创建需要的具体策略 */
        IStrategy strategy1 = new Strategy1();
        /* 然后创建执行过程 */
        Context context = new Context();
        /* 将策略放入执行过程 */
        context.setStrategy(strategy1);
        /* 添加上我们的逻辑后,我们就可以开始执行策略了 */
        context.executeStrategy();
    }
}

应用场景

  1. 多个类只有在算法或行为上稍有不同的场景。
  2. 算法需要自由切换。
  3. 需要屏蔽算法规则。
  4. 如果具体策略数量大于3个,可以考虑使用混合模式。

策略模式的优缺点

优点

  1. 策略算法可以自由切换
  2. 避免使用多重条件判断,我们有这么多策略,不需要使用判断语句来判断需要使用哪种策略,我们这是被动选择策略。我们可以使用多态来,我们主动选择策略。
  3. 扩展性好,我们可以随时添加一个策略而不用改任何代码。

缺点

  1. 每个策略类就是一种策略,具体策略类不能被复用,这样策略变多,会显得很臃肿。
  2. 我们需要创建具体策略对象,这样所有的策略类都会向对外暴露,违反了迪米特法则。