1、含义
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
2、多态
在说策略模式之前说 面向对象编程三大特性中的多态;
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。策略模式正是借助于多态这一特性。
3、组成:
1、抽象策略角色:这个是一个抽象的角色,通常情况下使用接口或者抽象类去实现。对比来说,就是我们的Comparator接口。
2、具体策略角色:包装了具体的算法和行为。对比来说,就是实现了Comparator接口的实现一组实现类。
3、环境角色:内部会持有一个抽象角色的引用,给客户端调用。对比来说,就是我们的TreeSet类。说明:TreeSet内部一定会有一个策略类的一个成员变量,这样做的目的在于可以当我们在去创建TreeSet对象的时候,可以接收我们向TreeSet类中传递的具体的策略类。
4、代码
在理解以上的内容之后,我们编写一个实现加减乘除的小Demo。从代码的角度剖析一下策略模式。
4.1 定义抽象策略角色
/**
* @Author: LX 17839193044@162.com
* @Description: 声明抽象策略角色
* @Date: 20:14 2019/1/4
* @Version: V1.0
*/
public interface Strategy {
/**
* @Author: LX 17839193044@162.com
* @Description: 声明抽象策略方法 返回值、参数根据业务自行添加
* @Date: 2019/1/4 20:15
* @Version: V1.0
*/
int getResult(int numOne, int numTwo);
}
4.2 定义具体策略角色
具体策略角色一:数据相加
import cn.thislx.strategy.Strategy;
/**
* @Author: LX 17839193044@162.com
* @Description: 具体策略角色一
* @Date: 20:16 2019/1/4
* @Version: V1.0
*/
public class OneStrategy implements Strategy {
/**
* @param numOne: 数值一
* @param numTwo: 数值二
* @Author: LX 17839193044@162.com
* @Description: 具体策略实现方法一
* @Date: 2019/1/4 20:42
* @Version: V1.0
*/
@Override
public int getResult(int numOne, int numTwo) {
// 进行相应的业务处理
System.out.println("具体策略角色一执行,数值相加");
return numOne + numTwo;
}
}
具体策略角色二:数值相减
import cn.thislx.strategy.Strategy;
/**
* @Author: LX 17839193044@162.com
* @Description: 具体策略角色二
* @Date: 20:16 2019/1/4
* @Version: V1.0
*/
public class TwoStrategy implements Strategy {
/**
* @param numOne: 数值一
* @param numTwo: 数值二
* @Author: LX 17839193044@162.com
* @Description: 具体策略实现方法二
* @Date: 2019/1/4 20:42
* @Version: V1.0
*/
@Override
public int getResult(int numOne, int numTwo) {
// 进行相应的业务处理
System.out.println("具体策略角色二执行,数值相减");
return numOne - numTwo;
}
}
具体策略角色三:数据相乘
import cn.thislx.strategy.Strategy;
/**
* @Author: LX 17839193044@162.com
* @Description: 具体策略角色三
* @Date: 20:17 2019/1/4
* @Version: V1.0
*/
public class ThreeStrategy implements Strategy {
/**
* @param numOne: 数值一
* @param numTwo: 数值二
* @Author: LX 17839193044@162.com
* @Description: 具体策略实现方法三
* @Date: 2019/1/4 20:42
* @Version: V1.0
*/
@Override
public int getResult(int numOne, int numTwo) {
// 进行相应的业务处理
System.out.println("具体策略角色三执行,数值相乘");
return numOne * numTwo;
}
}
4.3 定义环境角色
import cn.thislx.strategy.Strategy;
import cn.thislx.strategy.impl.OneStrategy;
import cn.thislx.strategy.impl.ThreeStrategy;
import cn.thislx.strategy.impl.TwoStrategy;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: LX 17839193044@162.com
* @Description: 环境角色 内部持有一个抽象策略角色,给客户端调用
* @Date: 20:20 2019/1/4
* @Version: V1.0
*/
public class Context {
private static final String STRATEGY_ONE = "one";
private static final String STRATEGY_TWO = "two";
private static final String STRATEGY_THREE = "three";
/**
* 将全部具体策略角色放到map中。map类似于一个锦囊
*/
public static Map<String, Strategy> strategyMap = new HashMap<String, Strategy>() {{
put(STRATEGY_ONE, new OneStrategy());
put(STRATEGY_TWO, new TwoStrategy());
put(STRATEGY_THREE, new ThreeStrategy());
}};
/**
* 抽象策略角色 给客户端调用
*/
private Strategy strategy;
/**
* @param name: 锦囊中的key
* @Author: LX 17839193044@162.com
* @Description: 有参构造方法 使抽象策略角色实例化为具体策略角色
* @Date: 2019/1/4 20:50
* @Version: V1.0
*/
public Context(String name) {
strategy = strategyMap.get(name);
}
/**
* @param numOne 策略角色所需要的参数(根据业务需求选择参数类型)
* @param numTwo 策略角色所需要的参数(根据业务需求选择参数类型)
* @Author: LX 17839193044@162.com
* @Description: 策略角色的执行方法(调用的入口)
* @Date: 2019/1/4 20:51
* @Version: V1.0
*/
public int excute(int numOne, int numTwo) {
int result = strategy.getResult(numOne, numTwo);
return result;
}
}
4.4 编写测试方法
public class Main {
public static void main(String[] args) {
//实际开发中一定要避免硬编码问题,在此我不再提取。
int oneStrategyResult = new Context("one").excute(1, 2);
System.out.println("策略一执行结果:" + oneStrategyResult);
int twoStrategyResult = new Context("two").excute(1, 2);
System.out.println("策略二执行结果:" + twoStrategyResult);
int threeStrategyResult = new Context("three").excute(1, 2);
System.out.println("策略三执行结果:" + threeStrategyResult);
}
}