模式定义
策略模式,行为模式的一种,针对一组算法,将每一个算法封装到具有共同接口(也可能是共同的抽象类)的独立类,从而使它们可以相互替换。
关键词
- 一组算法,对象的某个属性针对不同操作可能有不同的赋值方式(如下例中图书价格的计算方式因会员等级而异)
- 共同接口(共同抽象类),不同算法能够相互替换的保障
使用场景
某个对象(如图书)的一些属性(如ISBN号)不变,但某些属性(如价格)是容易变化的,且该属性(价格)针对不同情况有不同的表现形式(不同的会员等级计算方式不一样)。对于这个容易变化的属性(如价格),我们不希望将其与图书这个对象绑定,而是希望图书能与计算价格的策略进行绑定。这种情形就是策略模式的体现了。也就是说策略模式是为了处理对象复杂多变的行为的。
举个例子
图书销售终端,计价策略:
- 初级会员,无折扣
- 中级会员,九折
- 高级会员,不折
现在一个高级会员购买一本售价为50元的书,具体代码实现:
定义共同接口(会员计价策略抽象接口)
1 | package com.rainmonth.pattern.behavioral.strategy.book; |
初级会员计价策略
1 | package com.rainmonth.pattern.behavioral.strategy.book; |
中级会员计价策略1
2
3
4
5
6
7
8
9
10
11
12
13package com.rainmonth.pattern.behavioral.strategy.book;
/**
* 中级会员销售策略
* Created by RandyZhang on 2017/10/19.
*/
public class IntermediateMemberStrategy implements MemberStrategy{
public double calculateActualSalePrice(double bookSalePrice) {
System.out.println("中级会员打九折");
return bookSalePrice * 0.8;
}
}
高级会员计价策略1
2
3
4
5
6
7
8
9
10
11
12
13package com.rainmonth.pattern.behavioral.strategy.book;
/**
* 高级会员销售策略
* Created by RandyZhang on 2017/10/19.
*/
public class AdvanceMemberStrategy implements MemberStrategy{
public double calculateActualSalePrice(double bookSalePrice) {
System.out.println("高级会员打八折");
return bookSalePrice * 0.9;
}
}
销售终端(实际调用)
1 | package com.rainmonth.pattern.behavioral.strategy.book; |
最终输出
1 | 高级会员打八折 |
模式深入
优缺点
根据上面的例子,可以总结出策略模式的优缺点。
优点
- 不同等级的计算策略容易管理。(我们可以很容易的新增或改变计算策略)
- 避免了多重if-else的判断(不用策略模式的话单纯使用if-else不易维护)
缺点
- 如果策略增多,策略对应的类就增多;
- 调用策略的人必须对所有策略烂熟于心,并且要知道什么时候调用什么策略。(有一定局限性,因为调用的客户段必须知道什么情形下采用什么策略)。
体现的多态思想
BookEntity持有MemberStrategy对象引用,在生成对象实例时,将其赋值为具体的子策略对象从而调用子策略对象中的策略方法,这就是多态的体现。
策略模式的重心
设计模式的产生很大程度上都是为了代码好维护、易扩展,这些都需要在代码的组织上下功夫,因此策略模式的重心不在算法的实现上(当然实现也很重要哦),而在算法的组织上。
算法的平等性与唯一性
平等性是说,每种策略都是平等的,被调用的优先级都是相同的,只要符合调用条件(如会员等级对应就可以调用);
唯一性是说,计算的时候,只可能使用其中的一种策略
Java中的应用
File类里面有个list方法,用来列出目录里面的所有文件,这是基本功能,但如果我们想获取目录里面某种规则的文件(如以.java结尾的文件)我们怎么办呢?Java I/O为我们提供了FilenameFilter这个接口,就文件名过滤。我们自定义一个类实现该接口就可以实现不同文件名的过滤(如JavaSuffixFilter、TxtSuffixFilter等),这就是策略模式的在Java I/O设计上的一个小小应用。
总结
对于策略模式,要牢记起关键词:一组算法和共同接口(共同抽象类),因为策略模式简单来说就是“准备一组算法,并将每个算法封装起来,使得它们可以互换(取代)”。