Define a familly algorithms, encapsulate each one, and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使他们之间互相转换)。
从以上官方定义分析到策略模式具有三个角色分别是:
我们分析一下计算器的简单运算,以加减法为例来划分一下其中的角色,比如 加法:1+1=2,减法1-1=0。这里加法和减法都是一个运算可以理解为两个策略;他们都有计算的功能需要定义一个接口提供统一的运算方法,这个为抽象策略角色;高层实现减价法则为封装角色及将接口放进去,通过接口调用,所以高层不用知道具体是加法还是减法。
因此封装角色起到了承上启下的作用,屏蔽了高层模块对策略、算法的直接访问,封装可能存在的变化。
下来简单实现计算器加减法的功能:
策略的接口,定义执行的方法:
package design.strategy.c001;
/**
* 定义策略接口(一组策略)
* @author yanwenfei
*
*/
public interface IStrategy {
//策略需要执行的方法
public int exec(int a, int b);
}
package design.strategy.c001;
/**
* 策略A加法
* @author yanwenfei
*
*/
public class StrategyADD implements IStrategy {
@Override
public int exec(int a, int b) {
return a+b;
}
}
package design.strategy.c001;
/**
* 减法策略
* @author yanwenfei
*
*/
public class StrategySub implements IStrategy {
@Override
public int exec(int a, int b) {
return a - b;
}
}
package design.strategy.c001;
/**
* 策略分装类
* @author yanwenfei
*/
public class Calculator {
private IStrategy strategy;
//切换策略
public Calculator(IStrategy strategy) {
this.strategy = strategy;
}
//执行策略方法
public int exec(int a, int b){
return strategy.exec(a, b);
}
}
package design.strategy.c001;
public class TestMain {
public static void main(String[] args) {
Calculator calculator = null;
IStrategy streadd = new StrategyADD();//创建加法策略;
calculator = new Calculator(streadd);//切换策略
int add = calculator.exec(20, 30);
System.out.println("20 + 30 = " + add);
IStrategy stresub = new StrategySub();//创建减法策略;
calculator = new Calculator(stresub);//切换策略
int sub = calculator.exec(20, 30);
System.out.println("20 - 30 = " + sub);
}
}
10 + 30 = 40
10 - 30 = -20
以上为策略模式传统的实现方式,肯定很多人能看出来这个策略模式有很多缺点,虽然便于扩展,但是每一个策略都是一个类,这个先不说,下来看一下很牛逼的策略枚举。
我们可以使用枚举在一个类中实现以上所有的功能及三种不同的角色,对不熟悉枚举的小伙伴可以查阅资料,下来看看通过枚举实现策略模式
package design.strategy.c002;
/**
* 策略枚举
* @author yanwenfei
*/
public enum Calculator {
ADD("+") {
@Override
public int exec(int a, int b) {
// TODO Auto-generated method stub
return a+b;
}
},
SUB("-") {
@Override
public int exec(int a, int b) {
// TODO Auto-generated method stub
return a-b;
}
};
public abstract int exec(int a, int b);
//运算符
private String value = "";
private Calculator(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
package design.strategy.c002;
public class TestMain {
public static void main(String[] args) {
int add = Calculator.ADD.exec(10, 30);
System.out.println("10 + 30 = "+add);
int sub = Calculator.SUB.exec(10, 30);
System.out.println("10 - 30 = "+sub);
}
}
10 + 30 = 40
10 - 30 = -20
在枚举类中,定义的抽象方法就像当时之前的接口,每一个枚举ADD SUB相当是一个具体的实现类(策略角色),而整个枚举类就是策略的分装角色。