最实用的设计模式:策略模式的快速理解
作者:鱼仔
博客首页: https://codeease.top
公众号:Java鱼仔
# (一)什么是策略模式
策略模式是设计模式中一个相对来说比较好理解,应用也十分广泛的设计模式。在我工作这些年所接触的项目中,有一个项目在整体上就使用了策略模式。在百科上,针对策略模式是这样介绍的:策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。
以某火锅品牌为例,同样是最后的收费环节,学生周末8.8折,工作日的指定时间6.9折,非学生全额支付。同样的收费方式在不同的情况下有不同的计算方式,这里就可以使用策略模式来实现。
# (二)策略模式中的几个角色
在策略模式中,有三种角色:
抽象策略(Strategy):定义实现策略所需要的接口。一般是定义接口或者抽象类。
具体策略(ConcreteStrategy):抽象策略的具体实现类,在策略模式中,每个算法都是一个具体策略。
上下文(Context):负责使用策略的角色,屏蔽高层模块对策略的直接访问。
# (三)策略模式的具体案例
还是以最开始的火锅店为例子。首先定义一个收费的策略接口,定义收费的方法:
public interface BillingStrategy {
void billing(BigDecimal amount);
}
2
3
接着写两个具体的策略:
// 周末8.8折
public class StudentWeekend implements BillingStrategy{
@Override
public void billing(BigDecimal amount) {
System.out.println("收了"+amount.multiply(new BigDecimal("0.88"))+"元");
}
}
2
3
4
5
6
7
// 工作日6.9折
public class StudentWorkingDay implements BillingStrategy{
@Override
public void billing(BigDecimal amount) {
System.out.println("收了"+amount.multiply(new BigDecimal("0.69"))+"元");
}
}
2
3
4
5
6
7
接着定义上下文角色,在这个例子中,负责使用策略的角色是火锅店:
public class Restaurant {
private BillingStrategy billingStrategy;
public Restaurant(BillingStrategy billingStrategy){
this.billingStrategy = billingStrategy;
}
public void billing(BigDecimal amount){
billingStrategy.billing(amount);
}
}
2
3
4
5
6
7
8
9
10
11
最后在Main方法中进行调用:
public class Main {
public static void main(String[] args) {
Restaurant restaurant1 = new Restaurant(new StudentWeekend());
restaurant1.billing(new BigDecimal("200"));
Restaurant restaurant2 = new Restaurant(new StudentWorkingDay());
restaurant2.billing(new BigDecimal("200"));
}
}
2
3
4
5
6
7
8
9
从结果可以看出,同样的收费方式,当传入的策略不同时,就可以采取不同的算法。
# (四)策略模式在源码中的应用
策略模式在开源代码和JDK源码中的应用十分广泛。
比如TreeMap在构造方法中引入Comparator排序策略,在put方法时根据不同的排序策略执行不同的排序方法:
又比如ThreadPoolExecutor这个线程池的类,在构造方法中传入拒绝策略,在reject方法中根据不同的拒绝策略执行具体的拒绝方法:
# (五)策略模式的理解
其实不使用设计模式,一样可以写代码,甚至可以写的更简单,但是设计模式考虑的是代码的扩展和可维护性。
策略模式最大的优点是很方便地替换策略,甚至还可以在程序运行过程中切换策略,也遵循了设计模式中的开闭原则,即对扩展开放,对封闭关闭。缺点是每新增一个策略就需要新增一个类,另外客户端必须知道所有的策略类。