设计模式——策略模式
应用场景
不要问我为何要给对策略模式单写一篇博客,在《大话设计模式》中介绍的第二个设计模式,就是“策略模式”,什么时候用到策略模式,在书中介绍了这样一个场景:你需要给某超市设计一个结帐系统,该系统需要对用户选择的商品进行一定的优惠计算,并最终得到结算价格;这些优惠可能是买五送一,可以是满100打八折等等。此时用策略模式的目的,则是将这些优惠算法进行封装,并通过封装后的context类,动态选择优惠算法,得到最后金额。
类图结构
代码实现
先看下优惠算法的基类接口
public interface IStrategy {
String getCash();
}
下面是几个优惠算法的基类实现
public class Strategy_A implements IStrategy{
@Override
public String getCash() {
// TODO Auto-generated method stub
String str = "这个是方法A";
System.out.println(str);
return str;
}
}
public class Strategy_B implements IStrategy{
public String getCash(){
String str = "这个是方法B";
System.out.println(str);
return str;
}
}
public class Strategy_C implements IStrategy{
public String getCash(){
String str = "这个是方法C";
System.out.println(str);
return str;
}
}
接下来是我们高潮部分,策略模式的精华所在,用于抽象出所有封装算法的环境类,该类可以动态的选择算法实现,并得到运算结果:
IStrategy strategy = null;
public Context(String func) {
switch (func) {
case "A":
strategy = new Strategy_A();
break;
case "B":
strategy = new Strategy_B();
break;
case "C":
strategy = new Strategy_C();
break;
default:
break;
}
}
public void getCash(){
strategy.getCash();
}
虽然我写的非常简单,但是还是要做个样子假装讲解一下:构造方法中“String func”参数是用于实现算法选择的依据。其中对于算法选择的模块,可以结合简单工厂设计模式来实现。
下面是程序入口:
public class TestMain {
public static void main(String argv[]) {
System.out.println("This is a strategy mode");
Context context = new Context("A");
context.getCash();
context = new Context("B");
context.getCash();
context = new Context("C");
context.getCash();
}
}
运行结果如下:
This is a strategy mode
这个是方法A
这个是方法B
这个是方法C
模式评价(优点和缺陷)
其实在上面context类的代码中,聪明如你,应该也能看出来,使用这种策略模式,客户必须对每种策略(即上面场景中的优惠算法)心知肚明。并且需要将相关参数传入context构造方法,才能获取相应的策略对象。同时,如果有了优惠策略有了变动,那么我们的context类也要做出相应的修改——添加或修改stategy(策略子类),事实上,这与程序设计中封闭开放原则(对改动封闭,对扩展开放)有所背离。
当然,好处也是显而易见的,你可以只用一个context对象,就可以得到最终的结果,相比于使用不同的stategy子类对象,操作成本得到了简化!