策略模式
顾名思义,我们来想象这样一个场景。商场有很多种打折方式,比如最近京东的满300送100,全场五折等等,商家销售的方式多种多样,如果我们用这样的场景来建模,你会怎么做呢?我们已经了解过了简单工厂模式,或许我们可以用简单工厂模式,抽象出一个用于计算最终消费者需要花多少钱的方法,然后对各种打折方式进行实现,增加一个工厂,根据客户端传递过来的标志量对打折方式的实例进行生产。这样做固然可以,但是我们可以想到,商家的打折方式是不确定的,可能今天采用这种打折方式,明天又会换一种打折方式,那么我们是不是得频繁修改这个工厂类呢?
oh,no。这样做显然是糟糕的,虽然可以实现,但是它应该不是好的实现方式,那么应该怎么实现呢?这时候我们就要用到策略模式了。
策略模式,它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
我们来看抽象的策略类:
1 package strategy; 2 3 //基本策略类,其他的算法类都会继承它 4 public abstract class BaseStrategy { 5 public abstract void doSomething(); 6 }
然后是各种算法的实现类:
1 public class StrategyA extends BaseStrategy{ 2 @Override 3 public void doSomething() { 4 System.out.println("strategyA:do something"); 5 } 6 } 7 8 public class StrategyB extends BaseStrategy{ 9 @Override 10 public void doSomething() { 11 System.out.println("strategyB:do something"); 12 } 13 }
Context类:
1 public class Context { 2 private BaseStrategy strategy; 3 4 public Context(BaseStrategy strategy) { 5 this.strategy = strategy; 6 } 7 8 public void doSomeThing(){ 9 strategy.doSomething(); 10 } 11 12 }
客户端调用:
1 public class MainClass { 2 public static void main(String[] args) { 3 Context context = new Context(new StrategyA()); 4 context.doSomeThing(); 5 6 context = new Context(new StrategyB()); 7 context.doSomeThing(); 8 } 9 }
我们对比策略模式和简单工厂模式的最大不同就在于工厂的规模上,简单工厂需要维护一个大的工厂类,然后客户端可以根据标志量进行生产,但是当工厂需要频繁的更改时,就需要用到策略模式了,它最大好处在于不需要维护一个工厂,各种实现相分离,改变策略了,只需客户端在调用时作出变化,而这种变化对其他策略来说是不可见的,最大限度的降低了耦合度。
所以说,策略模式是一种定义一系列算法的方法,从概念上看,这些算法都完成相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各类算法和调用算法类之间的耦合。
context定义了可重用的方法,继承有助于析取这些算法中的公共功能。
而且策略模式简化了测试,可以单独对每个算法进行测试。
策略模式是用来封装算法的,在基本的策略模式中,选择所用具体实现的职责由客户端承担,而传递给Context。