策略模式(Strategy)
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
类图:
- 1.Strategy:策略接口,用来约束一系列具体的策略算法。Context使用这个接口来调用具体的策略,实现定义的策略。
- 2.ConcreteStrategy:具体的策略实现,也就是具体的算法实现。
- 3.Context:上下午,负责与具体的策略交互,通常上下文会持有一个真正的策略实现。
策略模式是把一个类中经常改变或者将来可能改变的部分提取出来作为一个接口,然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。
现在我们要根据不同需求,计算两个数的四则运算( + - * /)
1. //策略定义算法的接口
2. publicinterfaceStrategy{
3. int calculate(int num1,int num2);
4. }
1. //具体算法,加法
2. publicclassOperationAddimplementsStrategy{
3. @Override
4. publicint calculate(int num1,int num2){
5. return num1 + num2;
6. }
7. }
1. //具体算法,减法
2. publicclassOperationSubstractimplementsStrategy{
3. @Override
4. publicint calculate(int num1,int num2){
5. return num1 - num2;
6. }
7. }
1. //具体算法,乘法
2. publicclassOperationMultiplyimplementsStrategy{
3. @Override
4. publicint calculate(int num1,int num2){
5. return num1 * num2;
6. }
7. }
1. //具体算法,除法
2. publicclassOperationDivideimplementsStrategy{
3. @Override
4. publicint calculate (int num1,int num2){
5. int res =0;
6. try{
7. res = num1 / num2;
8. }catch(Exception e){
9. e.printStackTrace();
10. }
11. return res;
12. }
13. }
1. //上下文
2. publicclassContext{
3. //持有一个具体策略对象
4. privateStrategy strategy;
5.
6. //传入一个具体策略对象
7. publicContext(Strategy strategy){
8. this.strategy =strategy;
9. }
10.
11. publicint calculate(int num1,int num2){
12. //调用具体策略对象进行算法运算
13. return strategy.calculate(num1,num2);
14. }
15. }
1. publicstaticvoid main(String[] args){
2. //计算 1 + 1
3. Context context =newContext(newOperationAdd());
4. System.out.println("1 + 1 = "+ context.calculate(1,1));
5. //计算 1 - 1
6. context =newContext(newOperationSubstract());
7. System.out.println("1 - 1 = "+context.calculate(1,1));
8. }
输出结果:
策略模式优点:
- 1.算法可以自由切换。
- 2.避免使用多重条件判断。
- 3.扩展性良好。
策略模式缺点:
- 1.策略类会增多。
- 2.所有策略类都需要对外暴露。
适用场景:
- 1.如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 2.一个系统需要动态地在几种算法中选择一种。
- 3.一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
经过上节你给保时捷进行装饰后,终于可与上市卖了。现在车的价格可能根据市场需求变动随时调整,对于不同销售商订购辆数进行优惠。5辆一下不打折,5-10辆9.5折,10-20辆9折,20辆以上8.5折。请你写个程序计算销售商预定x辆需要多少钱,价格y。
//策略接口,计算购车总金额
interface Strategy {
int calPrice(int price,int num);
}
//购买5辆及以下不打折
class Nodiscount implements Strategy {
@Override
public int calPrice(int price, int num) {
return price * num;
}
}
//购买6-10辆打9.5折
class Discount1 implements Strategy {
@Override
public int calPrice(int price, int num) {
return (int)(price * num * 0.95);
}
}
//补全,购买11-20辆打9折算法实现
class Discount2 implements Strategy {
@Override
public int calPrice(int price, int num) {
return (int)(price * num * 0.9);
}
}
//补全,购买20辆以上打8.5折算法实现
class Discount3 implements Strategy {
@Override
public int calPrice(int price, int num) {
return (int)(price * num * 0.85);
}
}
//上下文,根据不同策略来计算购车总金额
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int calPrice(int price, int num) {
//补全计算价格算法
if (num<5){
strategy=new Nodiscount();
}
else if ( num <=10 ){
strategy=new Discount1();
}
else if ( num <= 20 ){
strategy=new Discount2();
}
else if ( num > 20 ){
strategy=new Discount3();
}
return strategy.calPrice(price,num);
}
}
public class Main {
//每辆车单价10000
public static void main(String[] args) {
Strategy strategy;
//计算购买3辆总金额
strategy = new Nodiscount();
Context context = new Context(strategy);
System.out.println("购买3辆总金额: " + context.calPrice(10000,3));
//补全计算12辆总金额
System.out.println("购买12辆总金额: " + context.calPrice(10000,12));
}
}