1、定义
Define a family of algorithms, encapsulate each one, and make them interchangeable.
定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。
2、使用场景
- 多个类只是在算法或行为上稍有不同
- 算法需要自由切换
- 需要屏蔽算法规则
3、UML类图
角色说明:
- 上下文Context: 屏蔽高层模块对策略、算法的直接访问,它持有一个Strategy类的引用
- 抽象策略Strategy:对策略、算法进行抽象、
- ConcreteStrategyA、ConcreteStrategyB:是实现抽象策略中的具体操作,具体算法。
4、示例
以图书馆售书折扣为例,存在以下三种折扣算法:
- 算法1:对有些图书没有折扣,即折扣值算法中折扣值为0
- 算法2:对有些图书的折扣值是固定值为1元
- 算法3:对有些图书的折扣是15%
/**
* 抽象折扣算法
* @author Administrator
*
*/
public abstract class Strategy {
private double price;
private int number;
public Strategy(double price, int number) {
super();
this.price = price;
this.number = number;
}
public double getPrice() {
return price;
}
public int getNumber() {
return number;
}
// 策略算法,计算折扣额
public abstract double calculateDiscount();
}
/**
* 具体折扣类,没有折扣算法
* @author Administrator
*
*/
public class NoDiscountStrategy extends Strategy{
public NoDiscountStrategy(double price, int number) {
super(price, number);
}
/**
* 实现策略算法,0折扣算法
*/
@Override
public double calculateDiscount() {
return 0;
}
}
/**
* 具体折扣类,固定折扣值为1的算法
* @author Administrator
*
*/
public class FixDiscountStrategy extends Strategy{
public FixDiscountStrategy(double price, int number) {
super(price, number);
}
/**
* 实现策略算法,固定的折扣额
*/
@Override
public double calculateDiscount() {
return getNumber() * 2;
}
}
/**
* 具体的折扣,按照15%的折扣算法
* @author Administrator
*
*/
public class PercentageDiscountStrategy extends Strategy{
public PercentageDiscountStrategy(double price, int number) {
super(price, number);
}
/**
* 具体策略算法,15%的折扣额
*/
@Override
public double calculateDiscount() {
return getNumber() * getPrice() * 0.15;
}
}
/**
* 上下文文Context的实现
* @author Administrator
*
*/
public class ContextClient {
private Strategy strategy;
public ContextClient(Strategy strategy) {
super();
this.strategy = strategy;
}
/**
* 调用策略算法,计算折扣值
* @return
*/
public double calDiscount() {
return strategy.calculateDiscount();
}
public static void main(String[] args) {
ContextClient client0 = new ContextClient(new NoDiscountStrategy(48.5, 20));
System.out.println("0折扣:" + client0.calDiscount());
ContextClient clientFix = new ContextClient(new FixDiscountStrategy(48.5, 20));
System.out.println("固定折扣:" + clientFix.calDiscount());
ContextClient clientPer = new ContextClient(new PercentageDiscountStrategy(48.5, 20));
System.out.println("15%折扣:" + clientPer.calDiscount());
}
}
输出结果如下:
0折扣:0.0
固定折扣:40.0
15%折扣:145.5
5、总结
优点:
- 定义了一个算法和行为族,恰当的使用继承将公共的代码移到父类中,避免代码重复。
- 避免使用多重条件判断。
缺点:
- 客户端必须知道所有的策略类,并自行决定使用哪个策略类。
- 随着策略的增加,子类也会变得繁多。