策略模式属于对象的行为模式。其用意就是针对一组算法、将每一个算法封装到具有共同接口或者抽象类的独立类中,从而使它们可以相互替换。策略模式使的算法可以在不影响到客户端的情况下发生变化。
1、问题引入
现在有这么个场景、有一个售卖图书电子商务网站购物车系统。一个最简单的需求就是计算价格上。
1: 对有教材图书实行固定架构如每本一元。
2: 对有连环画提供7%的折扣、非教材计算机图书提供3%的折扣、其余图书没有折扣。
那么怎么解决这个问题尼??
解决方案
这里提供三种解决方案(当然方案还有很多)
- 所有业务逻辑都放到客户端里面、客户端利用条件选择语句来决定使用哪一个算法。这样以来客户端代码就会变的复杂和难以维护。
- 客户端可以使用继承的方式在子类中实现不同的行为。但是这样会使的行为和环境紧密的耦合在一起。强耦合使得两者不能单独演化。
- 使用策略模式。策略模式会把行为和环境分割开来。环境类负责维护和查询行为类。各种算法则在具体的策略类中是实现。由于算法和环境独立开、算法的增减和修改不会影响环境和客户端。
策略模式就是解决这个问题的系统化方法。当出现新的促销和折扣政策或者出现变化时。只需要新增策略类,并在客户端登记就可以了。策略模式可以看作是一个可插入算法。
下面我们就来看看策略模式是个什么鬼。
2、策略模式介绍
2.1、结构
策略模式是一个非常简单的模式、有多简单尼?看起来比单利还简单、但是要在工作中用好确实万难的。
如图有三个角色:
- Context(环境角色)
持有一个Strategy类的引用 - Strategy(抽象角色)
这是一个抽象角色,通常时由一个接口或者抽象类实现,此角色给出所有的具体策略类的所需要的接口。 - ConcreteStrategy(具体角色角色)
包装了相关算法或行为。
2.2、代码实现
代码实现其实很简单如下
代码清单1: 环境类的源代码
package com.xman.common.mongo.strategy;
/**
* @author yueli
* @date 2020-02-15 20:09
*/
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy \= strategy;
}
public void algorithm(){
strategy.algorithm();
}
}
代码清单2: 抽象策略类源代码
package com.xman.common.mongo.strategy;
/**
* @author yueli
* @date 2020-02-15 20:05
*/
public interface Strategy {
\* 策略方法 */
void algorithm();
}
代码清单3: 具体角色类源代码
package com.xman.common.mongo.strategy;
/**
* @author yueli
* @date 2020-02-15 20:08
*/
public class ConceteStrategy implements Strategy {
@Override
public void algorithm() {
// write you algorithm code hrer
}
}
注: 具体角色可以有多个实现、我在这里就不多写了。
还是那句话看着简单运用却不是那么容易。下面我们再来分析下它的优缺点。
2.3、优点
- 策略模式提供了对‘开闭原则’的完美支持,用户可以在不修改原有系统的基础上选择算法或者行为,也可以灵活的新增新的算法和行为。
- 策略模式提供了管理算法族的办法。
- 策略模式提供了可以替换继承关系的办法。
- 策略模式可以避免使用多重条件转移语句。
2.4、缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式造成产生很多策略类和对象,可以通过使用享元模式在一定程度上减少对象的数量。
2.4、使用场景
说完优缺点我们在来介绍下那些场景适合使用策略模式
- 一个系统类有很多个类,它们的却别仅在于它们的行为、这种情况使用策略模式可以动态的让一个对象在许多中行为中选择一种行为。
- 一个系统需要动态的在集中算法中选择一种。
- 一个系统算法使用的数据不可以让客户端知道、策略模式可以避免让客户端直接和算法数据接触。
- 一个对象有很多中行为,如果不恰当的使用模式、这些行为就只好使用多重条件选择语句来实现,说白了就是可以替换掉程序中大量的if{……}else if{……} ……。
3、总结
策略模式理解起来很简单,记住两点1、有三种角色。2、针对一组算法,管理一个算法族。
策略模式设计的原则有: 开闭原则、里氏代换原则。如有对设计模式设计的原则还不太了解的请移步到《设计模式六大原则、你还记得多少?》
好了!策略模式就介绍到这里,如有不正确的地方欢迎指正交流。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。