一、定义
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
意思是把算法给独立出来与使用它的客户解耦,并且这些算法是平等的,可以相互替换。
二、举例说明
记得看《三国演义》有一回是 玄德智激孙夫人,孔明三气周公瑾。在这一回中周瑜出了个馊主意:假借孙尚香嫁给刘备的名义,等刘备一来就扣留刘备,来换取荆州。在刘备出发前,诸葛亮给了赵云三个锦囊妙计,让他在危难时刻或者不知道该怎么办的时候,让他一一拆开看。
这锦囊妙计就是采用的策略模式。锦囊是上下文,锦囊中的妙计就是算法。如果诸葛亮直接告诉赵云这三个妙计。赵云该想了,草,我不信,我们还没去呢你诸葛就知道结果啥样了,你在牛逼,你也不能预知未来啊,不信。或者赵云相信了,CAO,过了几个月妈蛋给忘了,这刘备不就玩完了。其实乐不思蜀刘备在这也显露了,只不过在刘婵那更明显。
下面我看下策略模式的类图:
三、代码说明
先看看程序执行结果。
锦囊(上下文):
public class JinNang {
private MiaoJi miaoji;
public JinNang(MiaoJi miaoji){
this.miaoji = miaoji;
}
public void operation(){
miaoji.operation();
}
}
妙计:
public interface MiaoJi {
public void operation();
}
妙计一、
public class MiaojiOne implements MiaoJi {
@Override
public void operation() {
System.out.println("妙计:到东吴就拜会乔国老;");
}
}
妙计二、
public class MiaojiTwo implements MiaoJi {
@Override
public void operation() {
// TODO Auto-generated method stub
System.out.println("妙计:刘备被孙权设计留下就对他谎称曹操大军压境");
}
}
妙计三、
public class MiaojiThree implements MiaoJi {
@Override
public void operation() {
// TODO Auto-generated method stub
System.out.println("妙计:被东吴军队追赶就求孙夫人解围");
}
}
诸葛亮:
public class ZhuGeLiang {
private ArrayList<JinNang> jinNangs ;
private static ZhuGeLiang _instance;
private ZhuGeLiang(){
makeJinnang();
}
public static synchronized ZhuGeLiang getInstance(){
if(_instance==null){
_instance = new ZhuGeLiang();
}
return _instance;
}
public void makeJinnang(){
if(jinNangs==null){
jinNangs = new ArrayList<JinNang>();
}
jinNangs.clear();
jinNangs.add(new JinNang(new MiaojiOne()));
jinNangs.add(new JinNang(new MiaojiTwo()));
jinNangs.add(new JinNang(new MiaojiThree()));
}
public ArrayList<JinNang> getJinNang(){
return jinNangs;
}
}
赵云:
public class ZhaoYun {
ArrayList<JinNang> jinNangs;
public void getJinNangMiaoJi(){
jinNangs = ZhuGeLiang.getInstance().getJinNang();
}
public void openJinang(){
jinNangs.get(0).operation();
jinNangs.remove(0);
}
public void status(){
System.out.println("主公过江结亲");
openJinang();
System.out.println("主公完婚,和老婆如胶似漆,不思蜀");
openJinang();
System.out.println("主公返蜀途中,被东吴大兵追杀");
openJinang();
}
public static void main(String[] msg){
ZhaoYun zhaoyun = new ZhaoYun();
zhaoyun.getJinNangMiaoJi();
zhaoyun.status();
}
}
类图如下:
调用的顺序图为:
四、总结
1、Context和Strategy的关系
在策略模式中,通常是上下文使用具体的策略实现对象。反过来,策略实现对象也可以从上下文获取所需要的数据。因此可以将上下文当做参数传递给策略实现对象,这种情况下上下文和策略实现对象是紧密耦合的。在这种情况下,上下文封装着具体策略对象进行算法运算所需要的数据,具体策略对象通过回调上下文的方法来获取这些数据。
甚至在某些情况下,策略实现对象还可以回调上下文的方法来实现一定的功能,这种使用场景下,上下文变相充当了多个策略算法实现的公共接口。在上下文定义的方法可以当做是所有或者是部分策略算法使用的公共功能。
2、策略模式的优缺点
优点:
定义一系列的算法
策略模式的功能就是定义一系列算法,实现让这些算法可以相互替换。所以会为这一系列算法定义公共的接口,以约束一系列算法要实现的功能。如果这一系列算法具有公共功能,可以把策略接口实现为抽象类,把这些公共功能实现到父类中。
避免多重条件语句
根据前面的例子会发现,策略模式的一系列策略算法是平等的,是可以互换的,写在一起就是通过if-else结构来组织,如果此时具体的算法实现中又有条件语句,就构成了多重条件语句,使用策略模式能避免这样的多重条件语句。
更好的扩展性
在策略模式中扩展的策略实现非常容易,只要增加新的策略实现类,然后在使用策略的地方选择使用这个新的策略实现就可以了。
缺点:
客户必须了解每种策略的不同
策略模式也有缺点,比如让客户端来选择具体使用哪一个策略,这就需要客户了解所有的策略,还要了解各种策略的功能和不同,这样才能做出正确的选择,而且这样也暴露了策略的具体实现。
增加了对象的数目
3、策略模式的本质。
分离算法,选择实现。