策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改,这种类型的设计模式属于行为型模式。在策略模式中,我们创建表示多个策略的对象和一个行为随着策略对象改变而改变的 context 对象。每个策略对象会改变 context 对象的执行算法。这个描述读起来有点绕口,接下来笔者还是通过具体应用案例和代码演示,读者通过阅读代码就可以体会到Java设计模式中策略模式的精髓。
主要解决:在有多种算法或行为相似的情况下,使用 if...else(或者switch...case) 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为或算法。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:通过多态思想,多个策略对象实现同一个接口。
应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
演示实例:给定一个数值类型的字符串根据前置条件(动态的数据格式)转换成多种对象类型格式
实现
首先创建一个解析String的接口ParseStrUtil和实现了ParseStrUtil接口的三个策略类。Context 是一个使用了某种策略的类。我们的演示类使用 Context 和策略对象来演示 Context 在它所配置或使用的策略对象改变时的行为变化。
步骤 1:创建一个接口
public interface ParseStrUtil<T> {
public Class<?> parse(String body);
}
步骤 2:创建实现上述接口的三个策略类
public class IntType implements ParseStrUtil<Object>{
@Override
public Class<? extends Integer> parse(String body) {
return Integer.valueOf(Integer.parseInt(body)).getClass();
}
}
public class LongType implements ParseStrUtil<Object>{
@Override
public Class<? extends Integer> parse(String body) {
return Long.valueOf(Long.parseLong(body)).getClass();
}
}
public class DoubleType implements ParseStrUtil<Object>{
@Override
public Class<? extends Integer> parse(String body) {
return Double.valueOf(Double.parseDouble(body)).getClass();
}
}
步骤 3:创建Context类
public class Context{
private ParseStrUtil<?> body;
public Context(){}
public void setContext(ParseStrUtil<?> json){
this.body = json;
}
public Class<?> parseStr(String str){
return body.parse(str);
}
}
步骤 4:测试,使用 Context 来查看当它改变策略对象时的算法变化
public static void main(String[] args) {
Context context = new Context();
context.setContext(new IntType());
System.out.println("String -->>>" + context.parseStr("20"));
context.setContext(new LongType());
System.out.println("String -->>>" + context.parseStr("20"));
context.setContext(new DoubleType());
System.out.println("String -->>>" + context.parseStr("20"));
System.out.println("可以看到调用的相同的方法传入的参数是相同的,但是最终转换后的数据格式是不一样的");
}
控制台打印结果:
String -->>>class java.lang.Integer
String -->>>class java.lang.Long
String -->>>class java.lang.Double
可以看到调用的相同的方法传入的参数是相同的,但是最终转换后的数据格式是不一样的
可以看出:策略模式主要是用来封装一组可以互相替代的算法族,并且可以根据需要动态地去替换 Context 使用的算法或者行为