设计模式的一句话 :过分设计是一种罪过,要根据项目实事求是,没有任何一种设计是一步到位,很多功能都是根据反馈进行改善。
1、背景:在实际开发中,我们常常遇见实现某种业务功能时,有许多不同实现方式,使用者可以任意选择其中的一种方式。例如,在排序某个序列数据时,我们可以选择冒泡排序、快速排序、插入排序、堆排序等等。我们在开发过程中,通常会选择将不同的算法以硬编码的方式封装到一个类当中,当我们需要添加新的算法时,会去修改这个类,修改某个算法时也会修改这个类。这样,每次改动都涉及到其他算法也要发布版本,可能引起新的错误,造成系统的不稳定,也增加测试的工作量。那么,有没有一种通用的设计模式,每次添加或修改某算法时,只需编写该算法就行了,从而最低限度地改动其他代码呢。这是就是今天要探讨的“策略模式”
2、例子
2.1 在进行某个活动推广时,用户可以通过多种方式参加活动,目前有“发表微博”,“发表微信”和“推荐用户”三种方式,假如活动可能会随时增加新的参与方式,或者修改某个参与方式的流程。我们的要求是尽可能不影响已有的其他的参与方式,这样我们就不用担心新增或者修改某参与方式时,造成其他参与方式出现新的错误。
2.2 一个经典的场景就是用户可以根据自己的实际情况选择去旅游,比如从广州去厦门旅游,用户可以灵活选择飞机、火车、大巴等等 不同的方式
3、策略模式
3.1 策略模式(Strategy):动态定义了一序列算法,它们之间可以相互替换,此模式在添加新的算法或修改算法时,让修改的代码达到最小化,提高系统可扩展性。
3.2 策略模式的UML图,如下:
Context环境类:维护一个Strategy父类,引用一个具体的ConcreteStrategy对象。
Strategy:策略的共同接口,声明要实现的接口
ConcreteStrategy:具体的策略实现类,实现Strategy接口,如ConcreteStrategyA、ConcreteStrategyB等。
3.3 优缺点:
优点:a.可以提供算法的替换,根据不用需求,选择不同的策略
b.降低了各个算法的耦合,修改和添加某算法时,不影响其他算法
缺点:a.增加了算法ConcreteStrategy实现类通讯的成本,也就是传 参的复杂性。
b.需要通过if else来选择不同的策略实现
针对以上的情况,可以结合简单工场模式,利用反射进行实例化具体的策略实现类,消除if else 判断,这样环境类Context就可以保持不变
4、源代码实现参考
4.1 策略接口Strategy
public interface IStrategy {
public void getPrice();//抽奖的具体方式
}
4.2 策略具体实现类
//具体策略A
public class ConcreteStrategyA implements IStrategy {
@Override
public void getPrice() {
System.out.println("========抽奖方式A=======");
}
}
//策略B
public class ConcreteStrategyB implements IStrategy {
@Override
public void getPrice() {
System.out.println("========抽奖方式B=======");
}
}
4.3 环境类Context
/**
* 环境类---》生成具体的策略
*/
public class Context {
private IStrategy strategy;
public Context(IStrategy strategy){
this.strategy = strategy;
}
public Context(){}
//利用简单工程方式,生产策略的具体实例
public void createStrategy(String strategy){
try {
this.strategy = (IStrategy) Class.forName(strategy).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
public void getPrice(){
strategy.getPrice();
}
}
4.4 客户端Client
public class Client {
public static void main(String[] args) {
doGetPrice();
}
public static void doGetPrice(){
Context context = new Context(new ConcreteStrategyA());
context.getPrice();
//通过反射机制创建策略实例,降低环境类的耦合
Context context2 = new Context();
context2.createStrategy("com.jimi.test.designpattern.strategy.activity.ConcreteStrategyB");
context2.getPrice();
}
}