每天都要完成一个小目标
一,定义
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化
什么意思呢?在我们平时的开发中,难免会遇到这种情况,实现某一个功能会有多种算法,如果我们将这些算法都放到一个类里面,通过if else 来选择具体的算法,那么这个类就会变得臃肿,维护成本也会提高,后面如果再增加一种算法,就需要修改这个类本身,这违反了OCP原则和单一职责原则。
如果我们将这些算法抽象出来,提供一个统一的接口,不同的算法有不同的实现类,这样在程序客户端就可以通过注入不同的实现对象来实现算法的动态替换,这种方式可扩展性,维护性高,这就是策略模式。
二,使用场景
1,针对同一类型问题的多种处理方式,仅仅是具体行为有差别时。
2,需要安全的封装多种同一类型的操作时。
3,出现同一抽象类有多个子类,而又需要使用if-else 或者switch case来选择具体子类时。
三,使用案例
假设有一个队列的排序功能,有三种算法,正序,倒序,随机排序。
如果不用策略模式,实现方式为:
先实现具体的策略类,根据不同的值采用不同的算法:
public class NormalStrategy {
private static final String TAG = "NormalStrategy";
public void order(String strategy){
if(strategy.equals("order")){
//正序算法
Log.d(TAG,"1,2,3,4,5,6,7,8,9");
}else if(strategy.equals("inorder")){
//倒序算法
Log.d(TAG,"9,8,7,6,5,4,3,2,1");
}else {
//随机数
Log.d(TAG,"5,4,6,7,8,9,2,3,1");
}
}
}
具体应用:
NormalStrategy normalStrategy =new NormalStrategy();
normalStrategy.order("order");
normalStrategy.order("inorder");
normalStrategy.order("random");
输出:
如果我们 再增加一种排序算法,就需要修改策略类,比如,我们再增加一中算法,让1在第二位输出:
public class NormalStrategy {
private static final String TAG = "NormalStrategy";
public void order(String strategy){
if(strategy.equals("order")){
//正序算法
Log.d(TAG,"1,2,3,4,5,6,7,8,9");
}else if(strategy.equals("inorder")){
//倒序算法
Log.d(TAG,"9,8,7,6,5,4,3,2,1");
}else if(strategy.equals("random")){
//随机数
Log.d(TAG,"5,4,6,7,8,9,2,3,1");
}else {
//让1在第二位输出
Log.d(TAG,"2,1,3,4,5,6,7,8,9");
}
}
}
具体应用:
NormalStrategy normalStrategy =new NormalStrategy();
normalStrategy.order("order");
normalStrategy.order("inorder");
normalStrategy.order("random");
normalStrategy.order("new");
输出:
那下面我们使用策略模式来实现:
首先创建一个抽象的策略接口:
/**
* 排序策略接口
* */
public interface Strategy {
void orderStrategy();
}
然后实现具体的策略类:
正序策略类
public class OrderStrategy implements Strategy{
private static final String TAG = "OrderStrategy";
@Override
public void orderStrategy() {
//正序算法
Log.d(TAG,"1,2,3,4,5,6,7,8,9");
}
}
倒序策略类
public class InOrderStrategy implements Strategy{
private static final String TAG = "InOrderStrategy";
@Override
public void orderStrategy() {
//倒序算法
Log.d(TAG,"9,8,7,6,5,4,3,2,1");
}
}
随机数策略类
public class RandomStrategy implements Strategy{
private static final String TAG = "RandomStrategy";
@Override
public void orderStrategy() {
//随机数算法
Log.d(TAG,"5,4,6,7,8,9,2,3,1");
}
}
策略类的中转上下文类
public class StrategyImp {
private Strategy strategy;
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void order(){
strategy.orderStrategy();
}
}
具体的实现
StrategyImp strategyImp =new StrategyImp();
strategyImp.setStrategy(new OrderStrategy());
strategyImp.order();
strategyImp.setStrategy(new InOrderStrategy());
strategyImp.order();
strategyImp.setStrategy(new RandomStrategy());
strategyImp.order();
输出:
如果在增加一种排序算法的话,就不需要修改现有的代码,只需要新建一个类,实现策略接口即可。假如现在还要再增加一中排序算法,让1在第二位输出,那么实现为:
public class NewStrategy implements Strategy{
private static final String TAG = "NewStrategy";
@Override
public void orderStrategy() {
//让1在第二位输出
Log.d(TAG,"2,1,3,4,5,6,7,8,9");
}
}
至此,就完成了策略模式的封装。
四,总结
策略模式主要用来分离算法,在相同的行为抽象下有不同的具体实现策略。
优点 :
1,结构清晰明了,使用简单直观
2,耦合度低,扩展性强
3,操作封装也更为彻底,数据更为安全
缺点 :
随着策略的增加,子类也会变得繁多
参考文献:Android源码设计模式第二版