介绍
- 策略模式 :(Strategy Pattern) 中定义算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的用户
- 这个算法体现了几个设计原则,第一:把变化的代码从不变的代码中国好分离出来,第二:针对接口编程,而不是实体类,(定义了策略接口)第三:多用组合 少用继承 (客户使用组合的方式使用策略)
- Context :是上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用
- Strategy:是策略类,用于定义所有支持算法的公共接口
- ConcreteStrategy是具体策略类,封装了具体的算法或行为,继承于Strategy。
案例
支付案例:
- 在我们日常项目中我们会遇到 接入 微信支付、支付宝支付、银行卡支付、苹果支付等
定义策略接口
public interface PayStrategy {
/**
* 支付 统一下单接口
* @param orderId
* @param price
*/
void unifiedOrder(Integer orderId, BigDecimal price);
/**
* 退款接口
* @param orderId
* @return
*/
boolean refund(Integer orderId);
}
策略实现类 微信支付
public class WeChatPayStrategy implements PayStrategy {
@Override
public void unifiedOrder(Integer orderId, BigDecimal price) {
System.out.println("微信下单支付");
}
@Override
public boolean refund(Integer orderId) {
System.out.println("微信退款成功");
return true;
}
}
策略实现类 支付宝支付
public class AlipayPayStrategy implements PayStrategy{
@Override
public void unifiedOrder(Integer orderId, BigDecimal price) {
System.out.println("支付宝下单支付");
}
@Override
public boolean refund(Integer orderId) {
System.out.println("支付宝退款成功");
return true;
}
}
策略实现类 银行卡支付
public class CardPayStrategy implements PayStrategy{
@Override
public void unifiedOrder(Integer orderId, BigDecimal price) {
System.out.println("银行卡下单支付");
}
@Override
public boolean refund(Integer orderId) {
System.out.println("银行卡退款成功");
return true;
}
}
策略实现类 苹果支付
public class ApplePayStrategy implements PayStrategy{
@Override
public void unifiedOrder(Integer orderId, BigDecimal price) {
System.out.println("苹果下单支付");
}
@Override
public boolean refund(Integer orderId) {
System.out.println("苹果退款成功");
return true;
}
}
Context 类
public class PayContext {
PayStrategy payStrategy;
public PayContext(PayStrategy payStrategy) {
this.payStrategy = payStrategy;
}
public void getPay(){
payStrategy.unifiedOrder(new Random(10).nextInt(),new BigDecimal("1"));
}
public void getRefund(){
payStrategy.refund(new Random(10).nextInt());
}
}
客户端
public class Client {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入支付方式(1微信/2支付宝/3银行卡/4苹果支付):");
int in = scanner.nextInt();
PayContext payContext = null;
switch (in){
case 1:
payContext = new PayContext(new WeChatPayStrategy());
break;
case 2:
payContext = new PayContext(new AlipayPayStrategy());
break;
case 3:
payContext = new PayContext(new CardPayStrategy());
break;
case 4:
payContext = new PayContext(new ApplePayStrategy());
break;
}
payContext.getPay();
payContext.getRefund();
}
}
优点和缺点
优点:
1)算法可以自由切换
2)避免使用多重条件判断(如果不用策略模式我们可能会使用多重条件语句,不利于维护)
3)扩展性良好,增加一个策略只需实现接口即可
缺点:
1)策略类数量会增多,每个策略都是一个类
2)所有的策略类都需要对外暴露
适用场景:
1) 算法需要自由切换的场景: 商场促销方式,打折、满减等
JDK中实现
- 比较器Comparator
Integer[] data = {12, 2, 3, 2, 4, 5, 1};
// 实现降序排序
Arrays.sort(data, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]
Arrays.sort();中可以指定比较器,实现comparator接口的比较器,作为对象传入
- ThreadPoolExecutor中的四种拒绝策略
/**
* 自定义拒绝策略
**/
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
}
});
//也可以实现它的子类
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy);
这里使用的就是策略模式。 RejectedExecutionHandler 的实现类
- AbortPolicy:直接抛出异常。
- CallerRunsPolicy:只用调用者所在线程来运行任务。
- DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
- DiscardPolicy:不处理,丢弃掉。
github Demo地址 : ~~~传送门~~~
个人博客地址:blog.yanxiaolong.cn/