一、策略模式定义
定义一组算法家族,每个算法都单独实现,让这些算法可以相互替换,此模式让算法的变化不影响使用算法的业务代码。
策略模式主要使用的就是多态机制, 其通用例图如下:
IStrategy:抽象的策略类或者接口,定义算法策略的同样方法。
ConcreteStrategy:具体的策略类, 实现了具体的算法。
Context:上下文,用来维护一个IStrategy的引用对象。
二、代码示例
下面就是使用策略模式的一个小例子,当我们想要使用哪种策略模式,就在Context中去传入哪一种策略的具体算法。
public interface IStrategy {
//定义具体策略必须具有的方法
public void doSomething();
}
public class ConcreteStrategyA implements IStrategy{
public void doSomething(){
System.out.println("具体算法001");
}
}
public class ConcreteStrategyB implements IStrategy{
@Override
public void doSomething() {
System.out.println("具体算法002");
}
}
public class Context {
private IStrategy strategy = null;
public Context(IStrategy strategy){
this.strategy = strategy;
}
public void doSomething(){
this.strategy.doSomething();
}
}
public class Client {
public static void main(String[] args) {
Context context = new Context(new ConcreteStrategyA());
context.doSomething();
context = new Context(new ConcreteStrategyB());
context.doSomething();
}
}
三、策略模式的优缺点
优点:
- 1、策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
2、使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
缺点:
1、由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。
- 2、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。不过这一点可以通过使用简单工厂模式、代理模式和享元模式修正。
四、策略模式+简单工厂模式的组合使用
修改一下上面的Context类:
public class Context {
public static int STRATEGY_A = 1;
public static int STRATEGY_B = 2;
private IStrategy strategy = null;
public Context(int type) {
switch(type) {
case STRATEGY_A:
strategy = new ConcreteStrategyA();
break;
case STRATEGY_B:
strategy = new ConcreteStrategyB();
break;
}
}
public void doSomething(){
this.strategy.doSomething();
}
}
业务代码修改:
public class Client {
public static void main(String[] args) {
Context context = new Context(Context.STRATEGY_A);
context.doSomething();
context = new Context(Context.STRATEGY_B);
context.doSomething();
}
}
通过策略模式+简单工厂的结合, 进一步降低了代码的耦合性,业务代码只需要知道Context类即可, 不需要知道策略类是什么样的。
其实设计模式只是为我们提供了一种参考, 我们不管用哪一种设计模式,其实最终都是为了提升代码复用性、可维护性、可扩展性,降低代码耦合性等。我们心里也要时刻保牢记代码设计六大原则(单一职责、开放封闭、依赖倒转、接口隔离、里氏替换、迪米特法则),设计模式不管怎么变, 都是围绕这六大原则的。