一件事实是一条没有性别的真理。 — 纪伯伦
写在前面
策略模式的定义:定义一系列的算法,把每一个算法封装起来,并且使他们可以相互替换。策略模式使得算法可独立于使用它的客户而独立变化。

上下文角色(Context):用来操作策略的上下文环境,起到承上启下的作用,屏蔽高层模块对策略/算法的直接访问。
抽象策略类(Strategy):策略/算法的抽象类,通常是接口。
具体策略类(ConcreteStrategy):抽象策略类的具体实现。
认识策略
下面通过一个例子来认识策略模式:
中秋节放假了,我要回家看爸妈,而我回家的方式有火车,高铁和飞机,那么我就可以选择三者当中的任意一种方式回家。
1.抽象策略类
因为我要回家这件事情是确定的,但是回家的方式却有不同选择,所以将我要回家的行为定义为抽象的。
/**
* 抽象策略类
*/
public interface Strategy {
void goHome();
}
2.具体策略类
因为我回家的方式有火车,高铁和飞机,所以要定义三种策略实现不同的回家算法。
/**
* 具体策略类
*/
public class HuoCheStrategy implements Strategy {
@Override
public void goHome() {
Log.d("火车", "我最终选择乘坐火车回家!!!");
}
}
/**
* 具体策略类
*/
public class GaoTieStrategy implements Strategy {
@Override
public void goHome() {
Log.d("高铁", "我最终选择乘坐高铁回家!!!");
}
}
/**
* 具体策略类
*/
public class FeiJiStrategy implements Strategy {
@Override
public void goHome() {
Log.d("飞机", "我最终选择乘坐飞机回家!!!");
}
}
3.上下文角色
回家的三种策略定义好了,那么要如何通过上下文角色来使用策略呢,前面说过上下文角色起到了承上启下的作用,也就是说只要我告诉上下文角色选择哪种策略回家,上下文角色就会使用哪种策略。
/**
* 上下文角色
*/
public class Context {
private Strategy mStrategy;
public Context(Strategy strategy) {
mStrategy = strategy;
}
public void goHome() {
mStrategy.goHome();
}
}
4.使用策略
现在我要回家了,那么我就可以通过给上下文角色传入不同的策略,就可以选择不同的方式回家了。
/**
* 客户端
*/
public class Client {
public Client() {
Context context;
// 选择火车策略
context = new Context(new HuoCheStrategy());
context.goHome();
// 选择高铁策略
context = new Context(new GaoTieStrategy());
context.goHome();
// 选择飞机策略
context = new Context(new FeiJiStrategy());
context.goHome();
}
}
总结
策略模式的使用场景:
- 对客户隐藏具体策略/算法的实现细节,彼此完全独立。
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时。
- 在一个类中定义了很多行为,而且这些行为在这个类里的操作以多个条件语句的形式出现。策略模式将相关的条件分支一如它们各自的Strategy类中,以代替这些条件语句。
策略模式的优点:
- 使用策略模式可以避免使用多重条件语句,多重条件语句不易维护,而且容易出错。
- 易于扩展,当需要添加一个策略时,只需实现接口就可以了。
策略模式的缺点:
- 每一个策略都是一个类,复用性小。策略越多,类的数量就越多。
- 上层模块必须知道有哪些策略,才能够使用这些策略,这与迪米特原则相违背。
网友评论